diff --git a/src/doc/reference.md b/src/doc/reference.md index 7d3cf64e9f031..21e9be59ebbdf 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -3529,7 +3529,9 @@ The actual implementation for each vtable entry can vary on an object-by-object basis. Note that for a trait object to be instantiated, the trait must be -_object-safe_. Object safety rules are defined in [RFC 255][rfc255]. +_object-safe_. Object safety rules are defined in [RFC 255]. + +[RFC 255]: https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md Given a pointer-typed expression `E` of type `&T` or `Box`, where `T` implements trait `R`, casting `E` to the corresponding pointer type `&R` or diff --git a/src/doc/trpl/concurrency.md b/src/doc/trpl/concurrency.md index d6590e956a841..3c64e0b14de42 100644 --- a/src/doc/trpl/concurrency.md +++ b/src/doc/trpl/concurrency.md @@ -6,7 +6,7 @@ and more cores, yet many programmers aren't prepared to fully utilize them. Rust's memory safety features also apply to its concurrency story too. Even concurrent Rust programs must be memory safe, having no data races. Rust's type -system is up to the thread, and gives you powerful ways to reason about +system is up to the task, and gives you powerful ways to reason about concurrent code at compile time. Before we talk about the concurrency features that come with Rust, it's important diff --git a/src/doc/trpl/dining-philosophers.md b/src/doc/trpl/dining-philosophers.md index 81280e8920ca9..87877f02fac60 100644 --- a/src/doc/trpl/dining-philosophers.md +++ b/src/doc/trpl/dining-philosophers.md @@ -73,6 +73,9 @@ a name is all we need. We choose the [`String`][string] type for the name, rather than `&str`. Generally speaking, working with a type which owns its data is easier than working with one that uses references. +[struct]: structs.html +[string]: strings.html + Let’s continue: ```rust diff --git a/src/doc/trpl/enums.md b/src/doc/trpl/enums.md index ad15d19eae143..01905caf5ec0d 100644 --- a/src/doc/trpl/enums.md +++ b/src/doc/trpl/enums.md @@ -55,9 +55,6 @@ fn process_color_change(msg: Message) { } ``` -Both variants are named `Digit`, but since they’re scoped to the `enum` name -there's no ambiguity. - Not supporting these operations may seem rather limiting, but it’s a limitation which we can overcome. There are two ways: by implementing equality ourselves, or by pattern matching variants with [`match`][match] expressions, which you’ll @@ -66,3 +63,4 @@ equality yet, but we’ll find out in the [`traits`][traits] section. [match]: match.html [if-let]: if-let.html +[traits]: traits.html diff --git a/src/doc/trpl/guessing-game.md b/src/doc/trpl/guessing-game.md index e5702ed163542..e113ce9344976 100644 --- a/src/doc/trpl/guessing-game.md +++ b/src/doc/trpl/guessing-game.md @@ -213,12 +213,12 @@ The next part will use this handle to get input from the user: ``` Here, we call the [`read_line()`][read_line] method on our handle. -[Method][method]s are like associated functions, but are only available on a +[Methods][method] are like associated functions, but are only available on a particular instance of a type, rather than the type itself. We’re also passing one argument to `read_line()`: `&mut guess`. [read_line]: ../std/io/struct.Stdin.html#method.read_line -[method]: methods.html +[method]: method-syntax.html Remember how we bound `guess` above? We said it was mutable. However, `read_line` doesn’t take a `String` as an argument: it takes a `&mut String`. diff --git a/src/doc/trpl/iterators.md b/src/doc/trpl/iterators.md index e0cc45c254b99..a93f622e9c529 100644 --- a/src/doc/trpl/iterators.md +++ b/src/doc/trpl/iterators.md @@ -42,7 +42,7 @@ loop is just a handy way to write this `loop`/`match`/`break` construct. `for` loops aren't the only thing that uses iterators, however. Writing your own iterator involves implementing the `Iterator` trait. While doing that is outside of the scope of this guide, Rust provides a number of useful iterators -to accomplish various threads. Before we talk about those, we should talk about a +to accomplish various tasks. Before we talk about those, we should talk about a Rust anti-pattern. And that's using ranges like this. Yes, we just talked about how ranges are cool. But ranges are also very diff --git a/src/doc/trpl/match.md b/src/doc/trpl/match.md index 2bb2359ba5a01..113e218883b34 100644 --- a/src/doc/trpl/match.md +++ b/src/doc/trpl/match.md @@ -97,4 +97,4 @@ Unlike the previous uses of `match`, you can’t use the normal `if` statement to do this. You can use the [`if let`][if-let] statement, which can be seen as an abbreviated form of `match`. -[if-let][if-let.html] +[if-let]: if-let.html diff --git a/src/doc/trpl/mutability.md b/src/doc/trpl/mutability.md index 674d65974494e..7186c65cdf424 100644 --- a/src/doc/trpl/mutability.md +++ b/src/doc/trpl/mutability.md @@ -35,7 +35,7 @@ let y = &mut x; `y` is an immutable binding to a mutable reference, which means that you can’t bind `y` to something else (`y = &mut z`), but you can mutate the thing that’s -bound to `y`. (`*y = 5`) A subtle distinction. +bound to `y` (`*y = 5`). A subtle distinction. Of course, if you need both: diff --git a/src/doc/trpl/patterns.md b/src/doc/trpl/patterns.md index 266c1cafdee57..93df0f19e8eeb 100644 --- a/src/doc/trpl/patterns.md +++ b/src/doc/trpl/patterns.md @@ -66,7 +66,7 @@ match x { } ``` -This prints `something else` +This prints `something else`. # Bindings @@ -152,7 +152,7 @@ match x { } ``` -This prints `Got an int!` +This prints `Got an int!`. # ref and ref mut diff --git a/src/doc/trpl/structs.md b/src/doc/trpl/structs.md index ad7ead9319989..5729aeefbac9c 100644 --- a/src/doc/trpl/structs.md +++ b/src/doc/trpl/structs.md @@ -196,3 +196,5 @@ useful. For instance, a library may ask you to create a structure that implements a certain [trait][trait] to handle events. If you don’t have any data you need to store in the structure, you can just create a unit-like struct. + +[trait]: traits.html diff --git a/src/doc/trpl/the-stack-and-the-heap.md b/src/doc/trpl/the-stack-and-the-heap.md index f5654d6293991..c47dbd9789354 100644 --- a/src/doc/trpl/the-stack-and-the-heap.md +++ b/src/doc/trpl/the-stack-and-the-heap.md @@ -80,7 +80,7 @@ This memory is kind of like a giant array: addresses start at zero and go up to the final number. So here’s a diagram of our first stack frame: | Address | Name | Value | -+---------+------+-------+ +|---------|------|-------| | 0 | x | 42 | We’ve got `x` located at address `0`, with the value `42`. @@ -88,7 +88,7 @@ We’ve got `x` located at address `0`, with the value `42`. When `foo()` is called, a new stack frame is allocated: | Address | Name | Value | -+---------+------+-------+ +|---------|------|-------| | 2 | z | 100 | | 1 | y | 5 | | 0 | x | 42 | @@ -107,7 +107,7 @@ value being stored. After `foo()` is over, its frame is deallocated: | Address | Name | Value | -+---------+------+-------+ +|---------|------|-------| | 0 | x | 42 | And then, after `main()`, even this last value goes away. Easy! @@ -142,13 +142,13 @@ fn main() { Okay, first, we call `main()`: | Address | Name | Value | -+---------+------+-------+ +|---------|------|-------| | 0 | x | 42 | Next up, `main()` calls `foo()`: | Address | Name | Value | -+---------+------+-------+ +|---------|------|-------| | 3 | c | 1 | | 2 | b | 100 | | 1 | a | 5 | @@ -157,7 +157,7 @@ Next up, `main()` calls `foo()`: And then `foo()` calls `bar()`: | Address | Name | Value | -+---------+------+-------+ +|---------|------|-------| | 4 | i | 6 | | 3 | c | 1 | | 2 | b | 100 | @@ -170,7 +170,7 @@ After `bar()` is over, its frame is deallocated, leaving just `foo()` and `main()`: | Address | Name | Value | -+---------+------+-------+ +|---------|------|-------| | 3 | c | 1 | | 2 | b | 100 | | 1 | a | 5 | @@ -179,7 +179,7 @@ After `bar()` is over, its frame is deallocated, leaving just `foo()` and And then `foo()` ends, leaving just `main()` | Address | Name | Value | -+---------+------+-------+ +|---------|------|-------| | 0 | x | 42 | And then we’re done. Getting the hang of it? It’s like piling up dishes: you @@ -206,7 +206,7 @@ fn main() { Here’s what happens in memory when `main()` is called: | Address | Name | Value | -+---------+------+--------+ +|---------|------|--------| | 1 | y | 42 | | 0 | x | ?????? | @@ -218,7 +218,7 @@ it allocates some memory for the heap, and puts `5` there. The memory now looks like this: | Address | Name | Value | -+-----------------+------+----------------+ +|-----------------|------|----------------| | 230 | | 5 | | ... | ... | ... | | 1 | y | 42 | @@ -243,7 +243,7 @@ layout of a program which has been running for a while now: | Address | Name | Value | -+----------------------+------+----------------------+ +|----------------------|------|----------------------| | 230 | | 5 | | (230) - 1 | | | | (230) - 2 | | | @@ -272,7 +272,7 @@ when it was created. Great! So when `x` goes away, it first frees the memory allocated on the heap: | Address | Name | Value | -+---------+------+--------+ +|---------|------|--------| | 1 | y | 42 | | 0 | x | ?????? | @@ -305,7 +305,7 @@ fn main() { When we enter `main()`, memory looks like this: | Address | Name | Value | -+---------+------+-------+ +|---------|------|-------| | 1 | y | 0 | | 0 | x | 5 | @@ -315,7 +315,7 @@ memory location that `x` lives at, which in this case is `0`. What about when we call `foo()`, passing `y` as an argument? | Address | Name | Value | -+---------+------+-------+ +|---------|------|-------| | 3 | z | 42 | | 2 | i | 0 | | 1 | y | 0 | @@ -367,7 +367,7 @@ fn main() { First, we call `main()`: | Address | Name | Value | -+-----------------+------+----------------+ +|-----------------|------|----------------| | 230 | | 20 | | ... | ... | ... | | 2 | j | 0 | @@ -380,7 +380,7 @@ value pointing there. Next, at the end of `main()`, `foo()` gets called: | Address | Name | Value | -+-----------------+------+----------------+ +|-----------------|------|----------------| | 230 | | 20 | | ... | ... | ... | | 5 | z | 4 | @@ -397,7 +397,7 @@ since `j` points at `h`. Next, `foo()` calls `baz()`, passing `z`: | Address | Name | Value | -+-----------------+------+----------------+ +|-----------------|------|----------------| | 230 | | 20 | | ... | ... | ... | | 7 | g | 100 | @@ -413,7 +413,7 @@ We’ve allocated memory for `f` and `g`. `baz()` is very short, so when it’s over, we get rid of its stack frame: | Address | Name | Value | -+-----------------+------+----------------+ +|-----------------|------|----------------| | 230 | | 20 | | ... | ... | ... | | 5 | z | 4 | @@ -426,11 +426,11 @@ over, we get rid of its stack frame: Next, `foo()` calls `bar()` with `x` and `z`: | Address | Name | Value | -+----------------------+------+----------------------+ +|----------------------|------|----------------------| | 230 | | 20 | | (230) - 1 | | 5 | | ... | ... | ... | -| 10 | e | 4 | +| 10 | e | 9 | | 9 | d | (230) - 1 | | 8 | c | 5 | | 7 | b | 4 | @@ -449,13 +449,13 @@ case, we set up the variables as usual. At the end of `bar()`, it calls `baz()`: | Address | Name | Value | -+----------------------+------+----------------------+ +|----------------------|------|----------------------| | 230 | | 20 | | (230) - 1 | | 5 | | ... | ... | ... | | 12 | g | 100 | | 11 | f | 4 | -| 10 | e | 4 | +| 10 | e | 9 | | 9 | d | (230) - 1 | | 8 | c | 5 | | 7 | b | 4 | @@ -473,11 +473,11 @@ far. After `baz()` is over, we get rid of `f` and `g`: | Address | Name | Value | -+----------------------+------+----------------------+ +|----------------------|------|----------------------| | 230 | | 20 | | (230) - 1 | | 5 | | ... | ... | ... | -| 10 | e | 4 | +| 10 | e | 9 | | 9 | d | (230) - 1 | | 8 | c | 5 | | 7 | b | 4 | @@ -493,7 +493,7 @@ Next, we return from `bar()`. `d` in this case is a `Box`, so it also frees what it points to: (230) - 1. | Address | Name | Value | -+-----------------+------+----------------+ +|-----------------|------|----------------| | 230 | | 20 | | ... | ... | ... | | 5 | z | 4 | @@ -506,7 +506,7 @@ what it points to: (230) - 1. And after that, `foo()` returns: | Address | Name | Value | -+-----------------+------+----------------+ +|-----------------|------|----------------| | 230 | | 20 | | ... | ... | ... | | 2 | j | 0 | diff --git a/src/doc/trpl/while-loops.md b/src/doc/trpl/while-loops.md index e71d2033f49ed..a56c546b5516f 100644 --- a/src/doc/trpl/while-loops.md +++ b/src/doc/trpl/while-loops.md @@ -3,7 +3,7 @@ Rust also has a `while` loop. It looks like this: ```{rust} -let mut x = 5; // mut x: u32 +let mut x = 5; // mut x: i32 let mut done = false; // mut done: bool while !done { diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index baef6ba6f01f3..198627ad2fc3a 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -396,6 +396,7 @@ macro_rules! utf8_acc_cont_byte { #[stable(feature = "rust1", since = "1.0.0")] impl Borrow for String { + #[inline] fn borrow(&self) -> &str { &self[..] } } diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 9db1ceddf0d75..546e0bc806e12 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -665,14 +665,14 @@ macro_rules! iterator { #[inline] fn next(&mut self) -> Option<$elem> { // could be implemented with slices, but this avoids bounds checks - if self.ptr == self.end { - None - } else { - unsafe { - if mem::size_of::() != 0 { - ::intrinsics::assume(!self.ptr.is_null()); - ::intrinsics::assume(!self.end.is_null()); - } + unsafe { + if mem::size_of::() != 0 { + assume(!self.ptr.is_null()); + assume(!self.end.is_null()); + } + if self.ptr == self.end { + None + } else { let old = self.ptr; self.ptr = slice_offset!(self.ptr, 1); Some(slice_ref!(old)) @@ -710,15 +710,15 @@ macro_rules! iterator { #[inline] fn next_back(&mut self) -> Option<$elem> { // could be implemented with slices, but this avoids bounds checks - if self.end == self.ptr { - None - } else { - unsafe { + unsafe { + if mem::size_of::() != 0 { + assume(!self.ptr.is_null()); + assume(!self.end.is_null()); + } + if self.end == self.ptr { + None + } else { self.end = slice_offset!(self.end, -1); - if mem::size_of::() != 0 { - ::intrinsics::assume(!self.ptr.is_null()); - ::intrinsics::assume(!self.end.is_null()); - } Some(slice_ref!(self.end)) } } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 35abbc77c12b1..12d6fcd0303ec 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -30,6 +30,8 @@ #![feature(box_syntax)] #![feature(collections)] #![feature(core)] +#![feature(duration)] +#![feature(duration_span)] #![feature(fs_canonicalize)] #![feature(hash)] #![feature(into_cow)] diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 062a156637a35..9a95120ee686f 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -720,8 +720,7 @@ fn get_metadata_section(is_osx: bool, filename: &Path) -> Result {}ms", filename.file_name().unwrap(), - dur.num_milliseconds()); + info!("reading {:?} => {}", filename.file_name().unwrap(), dur); return ret.unwrap();; } diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index d71a68e205052..8d5357fa6e417 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -44,19 +44,24 @@ pub fn time(do_it: bool, what: &str, u: U, f: F) -> T where r }); - let mut u = Some(u); let mut rv = None; let dur = { let ref mut rvp = rv; Duration::span(move || { - *rvp = Some(f(u.take().unwrap())) + *rvp = Some(f(u)) }) }; let rv = rv.unwrap(); - println!("{}time: {}.{:03} \t{}", repeat(" ").take(old).collect::(), - dur.num_seconds(), dur.num_milliseconds() % 1000, what); + // Hack up our own formatting for the duration to make it easier for scripts + // to parse (always use the same number of decimal places and the same unit). + const NANOS_PER_SEC: f64 = 1_000_000_000.0; + let secs = dur.secs() as f64; + let secs = secs + dur.extra_nanos() as f64 / NANOS_PER_SEC; + println!("{}time: {:.3} \t{}", repeat(" ").take(old).collect::(), + secs, what); + DEPTH.with(|slot| slot.set(old)); rv diff --git a/src/librustc_back/archive.rs b/src/librustc_back/archive.rs index 37d784692fd0e..cad1522ee1344 100644 --- a/src/librustc_back/archive.rs +++ b/src/librustc_back/archive.rs @@ -306,6 +306,21 @@ impl<'a> ArchiveBuilder<'a> { if filename.contains(".SYMDEF") { continue } if skip(filename) { continue } + // Archives on unix systems typically do not have slashes in + // filenames as the `ar` utility generally only uses the last + // component of a path for the filename list in the archive. On + // Windows, however, archives assembled with `lib.exe` will preserve + // the full path to the file that was placed in the archive, + // including path separators. + // + // The code below is munging paths so it'll go wrong pretty quickly + // if there's some unexpected slashes in the filename, so here we + // just chop off everything but the filename component. Note that + // this can cause duplicate filenames, but that's also handled below + // as well. + let filename = Path::new(filename).file_name().unwrap() + .to_str().unwrap(); + // An archive can contain files of the same name multiple times, so // we need to be sure to not have them overwrite one another when we // extract them. Consequently we need to find a truly unique file diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 0073c0b061039..9c78c5aec00b4 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -383,17 +383,8 @@ pub fn phase_2_configure_and_expand(sess: &Session, -> Option { let time_passes = sess.time_passes(); - *sess.crate_types.borrow_mut() = - collect_crate_types(sess, &krate.attrs); - *sess.crate_metadata.borrow_mut() = - collect_crate_metadata(sess, &krate.attrs); - - time(time_passes, "recursion limit", (), |_| { - middle::recursion_limit::update_recursion_limit(sess, &krate); - }); - - // strip before expansion to allow macros to depend on - // configuration variables e.g/ in + // strip before anything else because crate metadata may use #[cfg_attr] + // and so macros can depend on configuration variables, such as // // #[macro_use] #[cfg(foo)] // mod bar { macro_rules! baz!(() => {{}}) } @@ -403,6 +394,15 @@ pub fn phase_2_configure_and_expand(sess: &Session, krate = time(time_passes, "configuration 1", krate, |krate| syntax::config::strip_unconfigured_items(sess.diagnostic(), krate)); + *sess.crate_types.borrow_mut() = + collect_crate_types(sess, &krate.attrs); + *sess.crate_metadata.borrow_mut() = + collect_crate_metadata(sess, &krate.attrs); + + time(time_passes, "recursion limit", (), |_| { + middle::recursion_limit::update_recursion_limit(sess, &krate); + }); + time(time_passes, "gated macro checking", (), |_| { let features = syntax::feature_gate::check_crate_macros(sess.codemap(), diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 1e0b627a8e031..15ddcbc80749c 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -49,6 +49,88 @@ about what constitutes an Item declaration and what does not: http://doc.rust-lang.org/reference.html#statements "##, +E0251: r##" +Two items of the same name cannot be imported without rebinding one of the +items under a new local name. + +An example of this error: + +``` +use foo::baz; +use bar::*; // error, do `use foo::baz as quux` instead on the previous line + +fn main() {} + +mod foo { + pub struct baz; +} + +mod bar { + pub mod baz {} +} +``` +"##, + +E0252: r##" +Two items of the same name cannot be imported without rebinding one of the +items under a new local name. + +An example of this error: + +``` +use foo::baz; +use bar::baz; // error, do `use bar::baz as quux` instead + +fn main() {} + +mod foo { + pub struct baz; +} + +mod bar { + pub mod baz {} +} +``` +"##, + +E0255: r##" +You can't import a value whose name is the same as another value defined in the +module. + +An example of this error: + +``` +use bar::foo; // error, do `use bar::foo as baz` instead + +fn foo() {} + +mod bar { + pub fn foo() {} +} + +fn main() {} +``` +"##, + +E0256: r##" +You can't import a type or module when the name of the item being imported is +the same as another type or submodule defined in the module. + +An example of this error: + +``` +use foo::Bar; // error + +type Bar = u32; + +mod foo { + pub mod Bar { } +} + +fn main() {} +``` +"##, + E0259: r##" The name chosen for an external crate conflicts with another external crate that has been imported into the current module. @@ -122,14 +204,10 @@ http://doc.rust-lang.org/reference.html#types register_diagnostics! { E0157, E0153, - E0251, // a named type or value has already been imported in this module - E0252, // a named type or value has already been imported in this module E0253, // not directly importable E0254, // import conflicts with imported crate in this module - E0255, // import conflicts with value in this module - E0256, // import conflicts with type in this module - E0257, // inherent implementations are only allowed on types defined in the current module - E0258, // import conflicts with existing submodule + E0257, + E0258, E0364, // item is private E0365 // item is private } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 447230ada2230..b5dd2f2909325 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2361,8 +2361,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { "type name" }; - let msg = format!("use of undeclared {} `{}`", kind, - path_names_to_string(path, 0)); + let self_type_name = special_idents::type_self.name; + let is_invalid_self_type_name = + path.segments.len() > 0 && + maybe_qself.is_none() && + path.segments[0].identifier.name == self_type_name; + let msg = if is_invalid_self_type_name { + "use of `Self` outside of an impl or trait".to_string() + } else { + format!("use of undeclared {} `{}`", + kind, path_names_to_string(path, 0)) + }; + self.resolve_error(ty.span, &msg[..]); } } @@ -2528,8 +2538,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // If anything ends up here entirely resolved, // it's an error. If anything ends up here // partially resolved, that's OK, because it may - // be a `T::CONST` that typeck will resolve to - // an inherent impl. + // be a `T::CONST` that typeck will resolve. if path_res.depth == 0 { self.resolve_error( path.span, @@ -2537,6 +2546,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { token::get_ident( path.segments.last().unwrap().identifier))); } else { + let const_name = path.segments.last().unwrap() + .identifier.name; + let traits = self.get_traits_containing_item(const_name); + self.trait_map.insert(pattern.id, traits); self.record_def(pattern.id, path_res); } } diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index fb2ad444005c3..90df0b853a083 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -16,12 +16,10 @@ use middle::def; use middle::privacy::{AllPublic, DependsOn, LastPrivate, LastMod}; use middle::subst; use middle::traits; -use middle::ty::*; -use middle::ty; +use middle::ty::{self, AsPredicate, ToPolyTraitRef}; use middle::infer; use util::ppaux::Repr; -use std::rc::Rc; use syntax::ast::DefId; use syntax::ast; use syntax::codemap::Span; @@ -39,7 +37,7 @@ pub enum MethodError { // Did not find an applicable method, but we did find various // static methods that may apply, as well as a list of // not-in-scope traits which may work. - NoMatch(Vec, Vec), + NoMatch(Vec, Vec, probe::Mode), // Multiple methods might apply. Ambiguity(Vec), @@ -62,7 +60,7 @@ type ItemIndex = usize; // just for doc purposes pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, method_name: ast::Name, - self_ty: Ty<'tcx>, + self_ty: ty::Ty<'tcx>, call_expr_id: ast::NodeId) -> bool { @@ -92,11 +90,11 @@ pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, method_name: ast::Name, - self_ty: Ty<'tcx>, - supplied_method_types: Vec>, + self_ty: ty::Ty<'tcx>, + supplied_method_types: Vec>, call_expr: &'tcx ast::Expr, self_expr: &'tcx ast::Expr) - -> Result, MethodError> + -> Result, MethodError> { debug!("lookup(method_name={}, self_ty={}, call_expr={}, self_expr={})", method_name.repr(fcx.tcx()), @@ -115,9 +113,9 @@ pub fn lookup_in_trait<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, self_expr: Option<&ast::Expr>, m_name: ast::Name, trait_def_id: DefId, - self_ty: Ty<'tcx>, - opt_input_types: Option>>) - -> Option> + self_ty: ty::Ty<'tcx>, + opt_input_types: Option>>) + -> Option> { lookup_in_trait_adjusted(fcx, span, self_expr, m_name, trait_def_id, 0, false, self_ty, opt_input_types) @@ -139,9 +137,9 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, trait_def_id: DefId, autoderefs: usize, unsize: bool, - self_ty: Ty<'tcx>, - opt_input_types: Option>>) - -> Option> + self_ty: ty::Ty<'tcx>, + opt_input_types: Option>>) + -> Option> { debug!("lookup_in_trait_adjusted(self_ty={}, self_expr={}, m_name={}, trait_def_id={})", self_ty.repr(fcx.tcx()), @@ -186,7 +184,9 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // Trait must have a method named `m_name` and it should not have // type parameters or early-bound regions. let tcx = fcx.tcx(); - let (method_num, method_ty) = trait_method(tcx, trait_def_id, m_name).unwrap(); + let (method_num, method_ty) = trait_item(tcx, trait_def_id, m_name) + .and_then(|(idx, item)| item.as_opt_method().map(|m| (idx, m))) + .unwrap(); assert_eq!(method_ty.generics.types.len(subst::FnSpace), 0); assert_eq!(method_ty.generics.regions.len(subst::FnSpace), 0); @@ -288,10 +288,10 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } } - let callee = MethodCallee { - origin: MethodTypeParam(MethodParam{trait_ref: trait_ref.clone(), - method_num: method_num, - impl_def_id: None}), + let callee = ty::MethodCallee { + origin: ty::MethodTypeParam(ty::MethodParam{trait_ref: trait_ref.clone(), + method_num: method_num, + impl_def_id: None}), ty: fty, substs: trait_ref.substs.clone() }; @@ -304,7 +304,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, method_name: ast::Name, - self_ty: Ty<'tcx>, + self_ty: ty::Ty<'tcx>, expr_id: ast::NodeId) -> Result<(def::Def, LastPrivate), MethodError> { @@ -322,9 +322,9 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, _ => def::FromTrait(pick.item.container().id()) }; let def_result = match pick.item { - ImplOrTraitItem::MethodTraitItem(..) => def::DefMethod(def_id, provenance), - ImplOrTraitItem::ConstTraitItem(..) => def::DefAssociatedConst(def_id, provenance), - ImplOrTraitItem::TypeTraitItem(..) => { + ty::ImplOrTraitItem::MethodTraitItem(..) => def::DefMethod(def_id, provenance), + ty::ImplOrTraitItem::ConstTraitItem(..) => def::DefAssociatedConst(def_id, provenance), + ty::ImplOrTraitItem::TypeTraitItem(..) => { fcx.tcx().sess.span_bug(span, "resolve_ufcs: probe picked associated type"); } }; @@ -332,31 +332,30 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } -/// Find method with name `method_name` defined in `trait_def_id` and return it, along with its -/// index (or `None`, if no such method). -fn trait_method<'tcx>(tcx: &ty::ctxt<'tcx>, - trait_def_id: ast::DefId, - method_name: ast::Name) - -> Option<(usize, Rc>)> +/// Find item with name `item_name` defined in `trait_def_id` and return it, along with its +/// index (or `None`, if no such item). +fn trait_item<'tcx>(tcx: &ty::ctxt<'tcx>, + trait_def_id: ast::DefId, + item_name: ast::Name) + -> Option<(usize, ty::ImplOrTraitItem<'tcx>)> { let trait_items = ty::trait_items(tcx, trait_def_id); trait_items .iter() .enumerate() - .find(|&(_, ref item)| item.name() == method_name) - .and_then(|(idx, item)| item.as_opt_method().map(|m| (idx, m))) + .find(|&(_, ref item)| item.name() == item_name) + .map(|(num, item)| (num, (*item).clone())) } -fn impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, - impl_def_id: ast::DefId, - method_name: ast::Name) - -> Option>> +fn impl_item<'tcx>(tcx: &ty::ctxt<'tcx>, + impl_def_id: ast::DefId, + item_name: ast::Name) + -> Option> { let impl_items = tcx.impl_items.borrow(); let impl_items = impl_items.get(&impl_def_id).unwrap(); impl_items .iter() .map(|&did| ty::impl_or_trait_item(tcx, did.def_id())) - .find(|m| m.name() == method_name) - .and_then(|item| item.as_opt_method()) + .find(|m| m.name() == item_name) } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 6171df218bb60..2eca855d5960b 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -136,7 +136,7 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let steps = if mode == Mode::MethodCall { match create_steps(fcx, span, self_ty) { Some(steps) => steps, - None => return Err(MethodError::NoMatch(Vec::new(), Vec::new())), + None => return Err(MethodError::NoMatch(Vec::new(), Vec::new(), mode)), } } else { vec![CandidateStep { @@ -866,7 +866,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { } } }).collect(), - Some(Err(MethodError::NoMatch(_, others))) => { + Some(Err(MethodError::NoMatch(_, others, _))) => { assert!(others.is_empty()); vec![] } @@ -877,7 +877,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { None => vec![], }; - Err(MethodError::NoMatch(static_candidates, out_of_scope_traits)) + Err(MethodError::NoMatch(static_candidates, out_of_scope_traits, self.mode)) } fn pick_core(&mut self) -> Option> { diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 17658675ee280..93239df60e164 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Give useful errors and suggestions to users when a method can't be +//! Give useful errors and suggestions to users when an item can't be //! found or is otherwise invalid. use CrateCtxt; @@ -27,12 +27,13 @@ use syntax::print::pprust; use std::cell; use std::cmp::Ordering; -use super::{MethodError, CandidateSource, impl_method, trait_method}; +use super::{MethodError, CandidateSource, impl_item, trait_item}; +use super::probe::Mode; pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, rcvr_ty: Ty<'tcx>, - method_name: ast::Name, + item_name: ast::Name, rcvr_expr: Option<&ast::Expr>, error: MethodError) { @@ -42,28 +43,30 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } match error { - MethodError::NoMatch(static_sources, out_of_scope_traits) => { + MethodError::NoMatch(static_sources, out_of_scope_traits, mode) => { let cx = fcx.tcx(); - let method_ustring = method_name.user_string(cx); + let item_ustring = item_name.user_string(cx); fcx.type_error_message( span, |actual| { - format!("type `{}` does not implement any \ - method in scope named `{}`", - actual, - method_ustring) + format!("no {} named `{}` found for type `{}` \ + in the current scope", + if mode == Mode::MethodCall { "method" } + else { "associated item" }, + item_ustring, + actual) }, rcvr_ty, None); - // If the method has the name of a field, give a help note + // If the item has the name of a field, give a help note if let (&ty::ty_struct(did, _), Some(_)) = (&rcvr_ty.sty, rcvr_expr) { let fields = ty::lookup_struct_fields(cx, did); - if fields.iter().any(|f| f.name == method_name) { + if fields.iter().any(|f| f.name == item_name) { cx.sess.span_note(span, &format!("use `(s.{0})(...)` if you meant to call the \ - function stored in the `{0}` field", method_ustring)); + function stored in the `{0}` field", item_ustring)); } } @@ -72,25 +75,25 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span, "found defined static methods, maybe a `self` is missing?"); - report_candidates(fcx, span, method_name, static_sources); + report_candidates(fcx, span, item_name, static_sources); } - suggest_traits_to_import(fcx, span, rcvr_ty, method_name, + suggest_traits_to_import(fcx, span, rcvr_ty, item_name, rcvr_expr, out_of_scope_traits) } MethodError::Ambiguity(sources) => { span_err!(fcx.sess(), span, E0034, - "multiple applicable methods in scope"); + "multiple applicable items in scope"); - report_candidates(fcx, span, method_name, sources); + report_candidates(fcx, span, item_name, sources); } MethodError::ClosureAmbiguity(trait_def_id) => { let msg = format!("the `{}` method from the `{}` trait cannot be explicitly \ invoked on this closure as we have not yet inferred what \ kind of closure it is", - method_name.user_string(fcx.tcx()), + item_name.user_string(fcx.tcx()), ty::item_path_str(fcx.tcx(), trait_def_id)); let msg = if let Some(callee) = rcvr_expr { format!("{}; use overloaded call notation instead (e.g., `{}()`)", @@ -104,7 +107,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, fn report_candidates(fcx: &FnCtxt, span: Span, - method_name: ast::Name, + item_name: ast::Name, mut sources: Vec) { sources.sort(); sources.dedup(); @@ -112,11 +115,11 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, for (idx, source) in sources.iter().enumerate() { match *source { CandidateSource::ImplSource(impl_did) => { - // Provide the best span we can. Use the method, if local to crate, else - // the impl, if local to crate (method may be defaulted), else the call site. - let method = impl_method(fcx.tcx(), impl_did, method_name).unwrap(); + // Provide the best span we can. Use the item, if local to crate, else + // the impl, if local to crate (item may be defaulted), else the call site. + let item = impl_item(fcx.tcx(), impl_did, item_name).unwrap(); let impl_span = fcx.tcx().map.def_id_span(impl_did, span); - let method_span = fcx.tcx().map.def_id_span(method.def_id, impl_span); + let item_span = fcx.tcx().map.def_id_span(item.def_id(), impl_span); let impl_ty = check::impl_self_ty(fcx, span, impl_did).ty; @@ -127,16 +130,16 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, trait_ref.def_id)), }; - span_note!(fcx.sess(), method_span, + span_note!(fcx.sess(), item_span, "candidate #{} is defined in an impl{} for the type `{}`", idx + 1, insertion, impl_ty.user_string(fcx.tcx())); } CandidateSource::TraitSource(trait_did) => { - let (_, method) = trait_method(fcx.tcx(), trait_did, method_name).unwrap(); - let method_span = fcx.tcx().map.def_id_span(method.def_id, span); - span_note!(fcx.sess(), method_span, + let (_, item) = trait_item(fcx.tcx(), trait_did, item_name).unwrap(); + let item_span = fcx.tcx().map.def_id_span(item.def_id(), span); + span_note!(fcx.sess(), item_span, "candidate #{} is defined in the trait `{}`", idx + 1, ty::item_path_str(fcx.tcx(), trait_did)); @@ -152,19 +155,19 @@ pub type AllTraitsVec = Vec; fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, rcvr_ty: Ty<'tcx>, - method_name: ast::Name, + item_name: ast::Name, rcvr_expr: Option<&ast::Expr>, valid_out_of_scope_traits: Vec) { let tcx = fcx.tcx(); - let method_ustring = method_name.user_string(tcx); + let item_ustring = item_name.user_string(tcx); if !valid_out_of_scope_traits.is_empty() { let mut candidates = valid_out_of_scope_traits; candidates.sort(); candidates.dedup(); let msg = format!( - "methods from traits can only be called if the trait is in scope; \ + "items from traits can only be used if the trait is in scope; \ the following {traits_are} implemented but not in scope, \ perhaps add a `use` for {one_of_them}:", traits_are = if candidates.len() == 1 {"trait is"} else {"traits are"}, @@ -185,7 +188,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let type_is_local = type_derefs_to_local(fcx, span, rcvr_ty, rcvr_expr); // there's no implemented traits, so lets suggest some traits to - // implement, by finding ones that have the method name, and are + // implement, by finding ones that have the item name, and are // legal to implement. let mut candidates = all_traits(fcx.ccx) .filter(|info| { @@ -196,7 +199,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // implementing a trait would be legal but is rejected // here). (type_is_local || ast_util::is_local(info.def_id)) - && trait_method(tcx, info.def_id, method_name).is_some() + && trait_item(tcx, info.def_id, item_name).is_some() }) .collect::>(); @@ -209,12 +212,12 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // of a type parameter: suggest adding a trait bound rather // than implementing. let msg = format!( - "methods from traits can only be called if the trait is implemented and in scope; \ - the following {traits_define} a method `{name}`, \ + "items from traits can only be used if the trait is implemented and in scope; \ + the following {traits_define} an item `{name}`, \ perhaps you need to implement {one_of_them}:", traits_define = if candidates.len() == 1 {"trait defines"} else {"traits define"}, one_of_them = if candidates.len() == 1 {"it"} else {"one of them"}, - name = method_ustring); + name = item_ustring); fcx.sess().fileline_help(span, &msg[..]); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 554f3d4b5a0c7..3cdbaec15284b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3082,8 +3082,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let mut checked = false; opt_place.as_ref().map(|place| match place.node { ast::ExprPath(None, ref path) => { - // FIXME(pcwalton): For now we hardcode the two permissible - // places: the exchange heap and the managed heap. + // FIXME(pcwalton): For now we hardcode the only permissible + // place: the exchange heap. let definition = lookup_full_def(tcx, path.span, place.id); let def_id = definition.def_id(); let referent_ty = fcx.expr_ty(&**subexpr); @@ -3097,7 +3097,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, if !checked { span_err!(tcx.sess, expr.span, E0066, - "only the managed heap and exchange heap are currently supported"); + "only the exchange heap is currently supported"); fcx.write_ty(id, tcx.types.err); } } @@ -3317,7 +3317,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span), result_type, ty::mk_nil(fcx.tcx())) { span_err!(tcx.sess, expr.span, E0069, - "`return;` in function returning non-nil"); + "`return;` in a function whose return type is \ + not `()`"); }, Some(ref e) => { check_expr_coercable_to_type(fcx, &**e, result_type); diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index a11a4edbd316b..58d0963274181 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -64,6 +64,43 @@ impl Foo for Bar { ``` "##, +E0053: r##" +For any given method of a trait, the mutabilities of the parameters must match +between the trait definition and the implementation. + +Here's an example where the mutability of the `self` parameter is wrong: + +``` +trait Foo { fn foo(&self); } + +struct Bar; + +impl Foo for Bar { + // error, the signature should be `fn foo(&self)` instead + fn foo(&mut self) { } +} + +fn main() {} +``` + +Here's another example, this time for a non-`self` parameter: + +``` +trait Foo { fn foo(x: &mut bool) -> bool; } + +struct Bar; + +impl Foo for Bar { + // error, the type of `x` should be `&mut bool` instead + fn foo(x: &bool) -> bool { *x } +} + +fn main() {} +``` + + +"##, + E0054: r##" It is not allowed to cast to a bool. If you are trying to cast a numeric type to a bool, you can compare it with zero instead: @@ -91,6 +128,16 @@ enum variant, one of the fields was not provided. Each field should be specified exactly once. "##, +E0066: r##" +Box placement expressions (like C++'s "placement new") do not yet support any +place expression except the exchange heap (i.e. `std::boxed::HEAP`). +Furthermore, the syntax is changing to use `in` instead of `box`. See [RFC 470] +and [RFC 809] for more details. + +[RFC 470]: https://github.com/rust-lang/rfcs/pull/470 +[RFC 809]: https://github.com/rust-lang/rfcs/pull/809 +"##, + E0067: r##" The left-hand side of an assignment operator must be an lvalue expression. An lvalue expression represents a memory location and includes item paths (ie, @@ -108,6 +155,21 @@ LinkedList::new() += 1; ``` "##, +E0069: r##" +The compiler found a function whose body contains a `return;` statement but +whose return type is not `()`. An example of this is: + +``` +// error +fn foo() -> u8 { + return; +} +``` + +Since `return;` is just like `return ();`, there is a mismatch between the +function's return type and the value being returned. +"##, + E0081: r##" Enum discriminants are used to differentiate enum variants stored in memory. This error indicates that the same value was used for two or more variants, @@ -302,6 +364,76 @@ it has been disabled for now. [iss20126]: https://github.com/rust-lang/rust/issues/20126 "##, +E0197: r##" +Inherent implementations (one that do not implement a trait but provide +methods associated with a type) are always safe because they are not +implementing an unsafe trait. Removing the `unsafe` keyword from the inherent +implementation will resolve this error. + +``` +struct Foo; + +// this will cause this error +unsafe impl Foo { } +// converting it to this will fix it +impl Foo { } +``` + +"##, + +E0198: r##" +A negative implementation is one that excludes a type from implementing a +particular trait. Not being able to use a trait is always a safe operation, +so negative implementations are always safe and never need to be marked as +unsafe. + +``` +struct Foo; + +// unsafe is unnecessary +unsafe impl !Clone for Foo { } +// this will compile +impl !Clone for Foo { } +``` + +"##, + +E0199: r##" +Safe traits should not have unsafe implementations, therefore marking an +implementation for a safe trait unsafe will cause a compiler error. Removing the +unsafe marker on the trait noted in the error will resolve this problem. + +``` +struct Foo; + +trait Bar { } + +// this won't compile because Bar is safe +unsafe impl Bar for Foo { } +// this will compile +impl Bar for Foo { } +``` + +"##, + +E0200: r##" +Unsafe traits must have unsafe implementations. This error occurs when an +implementation for an unsafe trait isn't marked as unsafe. This may be resolved +by marking the unsafe implementation as unsafe. + +``` +struct Foo; + +unsafe trait Bar { } + +// this won't compile because Bar is unsafe and impl isn't unsafe +impl Bar for Foo { } +// this will compile +unsafe impl Bar for Foo { } +``` + +"##, + E0201: r##" It is an error to define a method--a trait method or an inherent method--more than once. @@ -458,6 +590,48 @@ The `Sized` trait is a special trait built-in to the compiler for types with a constant size known at compile-time. This trait is automatically implemented for types as needed by the compiler, and it is currently disallowed to explicitly implement it for a type. +"##, + +E0368: r##" +This error indicates that a binary assignment operator like `+=` or `^=` was +applied to the wrong types. + +A couple examples of this are as follows: + +``` +let mut x: u16 = 5; +x ^= true; // error, `^=` cannot be applied to types `u16` and `bool` +x += (); // error, `+=` cannot be applied to types `u16` and `()` +``` + +Another problem you might be facing is this: suppose you've overloaded the `+` +operator for some type `Foo` by implementing the `std::ops::Add` trait for +`Foo`, but you find that using `+=` does not work, as in this example: + +``` +use std::ops::Add; + +struct Foo(u32); + +impl Add for Foo { + type Output = Foo; + + fn add(self, rhs: Foo) -> Foo { + Foo(self.0 + rhs.0) + } +} + +fn main() { + let mut x: Foo = Foo(5); + x += Foo(7); // error, `+= cannot be applied to types `Foo` and `Foo` +} +``` + +This is because the binary assignment operators currently do not work off of +traits, so it is not possible to overload them. See [RFC 953] for a proposal +to change this. + +[RFC 953]: https://github.com/rust-lang/rfcs/pull/953 "## } @@ -478,15 +652,12 @@ register_diagnostics! { E0040, // explicit use of destructor method E0044, // foreign items may not have type parameters E0045, // variadic function must have C calling convention - E0053, E0055, // method has an incompatible type for trait E0057, // method has an incompatible type for trait E0059, E0060, E0061, - E0066, E0068, - E0069, E0070, E0071, E0072, @@ -547,10 +718,6 @@ register_diagnostics! { E0194, E0195, // lifetime parameters or bounds on method do not match the trait declaration E0196, // cannot determine a type for this closure - E0197, // inherent impls cannot be declared as unsafe - E0198, // negative implementations are not unsafe - E0199, // implementing trait is not unsafe - E0200, // trait requires an `unsafe impl` declaration E0202, // associated items are not allowed in inherent impls E0203, // type parameter has more than one relaxed default bound, // and only one is supported @@ -606,7 +773,6 @@ register_diagnostics! { E0328, // cannot implement Unsize explicitly E0366, // dropck forbid specialization to concrete type or region E0367, // dropck forbid specialization to predicate not in struct/enum - E0368, // binary operation `=` cannot be applied to types E0369, // binary operation `` cannot be applied to types E0371, // impl Trait for Trait is illegal E0372, // impl Trait for Trait where Trait is not object safe diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 82999a47e5637..126ef38b9188f 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -243,6 +243,17 @@ impl Error for VarError { /// Sets the environment variable `k` to the value `v` for the currently running /// process. /// +/// Note that while concurrent access to environment variables is safe in Rust, +/// some platforms only expose inherently unsafe non-threadsafe APIs for +/// inspecting the environment. As a result extra care needs to be taken when +/// auditing calls to unsafe external FFI functions to ensure that any external +/// environment accesses are properly synchronized with accesses in Rust. +/// +/// Discussion of this unsafety on Unix may be found in: +/// +/// - [Austin Group Bugzilla](http://austingroupbugs.net/view.php?id=188) +/// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2) +/// /// # Examples /// /// ``` @@ -260,6 +271,17 @@ pub fn set_var, V: AsRef>(k: K, v: V) { /// Removes an environment variable from the environment of the currently running process. /// +/// Note that while concurrent access to environment variables is safe in Rust, +/// some platforms only expose inherently unsafe non-threadsafe APIs for +/// inspecting the environment. As a result extra care needs to be taken when +/// auditing calls to unsafe external FFI functions to ensure that any external +/// environment accesses are properly synchronized with accesses in Rust. +/// +/// Discussion of this unsafety on Unix may be found in: +/// +/// - [Austin Group Bugzilla](http://austingroupbugs.net/view.php?id=188) +/// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2) +/// /// # Examples /// /// ``` diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index c0d8d8eacf797..2e48cde18f361 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -28,7 +28,7 @@ //! //! The standard library is minimal, a set of battle-tested //! core types and shared abstractions for the [broader Rust -//! ecosystem][https://crates.io] to build on. +//! ecosystem](https://crates.io) to build on. //! //! The [primitive types](#primitives), though not defined in the //! standard library, are documented here, as are the predefined @@ -40,7 +40,7 @@ //! [`result`](result/index.html) modules define optional and //! error-handling types, `Option` and `Result`. The //! [`iter`](iter/index.html) module defines Rust's iterator trait, -//! [`Iterater`](iter/trait.Iterator.html), which works with the `for` +//! [`Iterator`](iter/trait.Iterator.html), which works with the `for` //! loop to access collections. //! //! The common container type, `Vec`, a growable vector backed by an array, diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index c2964b7a4f125..8da917916e5cd 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -69,12 +69,12 @@ pub struct Condvar { inner: Box } /// # Examples /// /// ``` -/// # #![feature(std_misc)] +/// # #![feature(static_condvar)] /// use std::sync::{StaticCondvar, CONDVAR_INIT}; /// /// static CVAR: StaticCondvar = CONDVAR_INIT; /// ``` -#[unstable(feature = "std_misc", +#[unstable(feature = "static_condvar", reason = "may be merged with Condvar in the future")] pub struct StaticCondvar { inner: sys::Condvar, @@ -82,7 +82,7 @@ pub struct StaticCondvar { } /// Constant initializer for a statically allocated condition variable. -#[unstable(feature = "std_misc", +#[unstable(feature = "static_condvar", reason = "may be merged with Condvar in the future")] pub const CONDVAR_INIT: StaticCondvar = StaticCondvar { inner: sys::CONDVAR_INIT, @@ -161,6 +161,30 @@ impl Condvar { } } + /// Waits on this condition variable for a notification, timing out after a + /// specified duration. + /// + /// The semantics of this function are equivalent to `wait()` except that + /// the thread will be blocked for roughly no longer than `dur`. This + /// method should not be used for precise timing due to anomalies such as + /// preemption or platform differences that may not cause the maximum + /// amount of time waited to be precisely `dur`. + /// + /// The returned boolean is `false` only if the timeout is known + /// to have elapsed. + /// + /// Like `wait`, the lock specified will be re-acquired when this function + /// returns, regardless of whether the timeout elapsed or not. + #[unstable(feature = "wait_timeout", reason = "waiting for Duration")] + pub fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>, + dur: Duration) + -> LockResult<(MutexGuard<'a, T>, bool)> { + unsafe { + let me: &'static Condvar = &*(self as *const _); + me.inner.wait_timeout(guard, dur) + } + } + /// Waits on this condition variable for a notification, timing out after a /// specified duration. /// @@ -214,7 +238,7 @@ impl StaticCondvar { /// notification. /// /// See `Condvar::wait`. - #[unstable(feature = "std_misc", + #[unstable(feature = "static_condvar", reason = "may be merged with Condvar in the future")] pub fn wait<'a, T>(&'static self, guard: MutexGuard<'a, T>) -> LockResult> { @@ -235,14 +259,27 @@ impl StaticCondvar { /// specified duration. /// /// See `Condvar::wait_timeout`. - #[unstable(feature = "std_misc", + #[unstable(feature = "static_condvar", reason = "may be merged with Condvar in the future")] pub fn wait_timeout_ms<'a, T>(&'static self, guard: MutexGuard<'a, T>, ms: u32) -> LockResult<(MutexGuard<'a, T>, bool)> { + self.wait_timeout(guard, Duration::from_millis(ms as u64)) + } + + /// Waits on this condition variable for a notification, timing out after a + /// specified duration. + /// + /// See `Condvar::wait_timeout`. + #[unstable(feature = "static_condvar", + reason = "may be merged with Condvar in the future")] + pub fn wait_timeout<'a, T>(&'static self, + guard: MutexGuard<'a, T>, + timeout: Duration) + -> LockResult<(MutexGuard<'a, T>, bool)> { let (poisoned, success) = unsafe { let lock = mutex::guard_lock(&guard); self.verify(lock); - let success = self.inner.wait_timeout(lock, Duration::milliseconds(ms as i64)); + let success = self.inner.wait_timeout(lock, timeout); (mutex::guard_poison(&guard).get(), success) }; if poisoned { @@ -259,7 +296,7 @@ impl StaticCondvar { /// passed and the function returns `false`. /// /// See `Condvar::wait_timeout_with`. - #[unstable(feature = "std_misc", + #[unstable(feature = "static_condvar", reason = "may be merged with Condvar in the future")] pub fn wait_timeout_with<'a, T, F>(&'static self, guard: MutexGuard<'a, T>, @@ -267,7 +304,8 @@ impl StaticCondvar { mut f: F) -> LockResult<(MutexGuard<'a, T>, bool)> where F: FnMut(LockResult<&mut T>) -> bool { - // This could be made more efficient by pushing the implementation into sys::condvar + // This could be made more efficient by pushing the implementation into + // sys::condvar let start = SteadyTime::now(); let mut guard_result: LockResult> = Ok(guard); while !f(guard_result @@ -277,12 +315,15 @@ impl StaticCondvar { let now = SteadyTime::now(); let consumed = &now - &start; let guard = guard_result.unwrap_or_else(|e| e.into_inner()); - let res = self.wait_timeout_ms(guard, (dur - consumed).num_milliseconds() as u32); - let (new_guard_result, no_timeout) = match res { - Ok((new_guard, no_timeout)) => (Ok(new_guard), no_timeout), - Err(err) => { - let (new_guard, no_timeout) = err.into_inner(); - (Err(PoisonError::new(new_guard)), no_timeout) + let (new_guard_result, no_timeout) = if consumed > dur { + (Ok(guard), false) + } else { + match self.wait_timeout(guard, dur - consumed) { + Ok((new_guard, no_timeout)) => (Ok(new_guard), no_timeout), + Err(err) => { + let (new_guard, no_timeout) = err.into_inner(); + (Err(PoisonError::new(new_guard)), no_timeout) + } } }; guard_result = new_guard_result; @@ -301,14 +342,14 @@ impl StaticCondvar { /// Wakes up one blocked thread on this condvar. /// /// See `Condvar::notify_one`. - #[unstable(feature = "std_misc", + #[unstable(feature = "static_condvar", reason = "may be merged with Condvar in the future")] pub fn notify_one(&'static self) { unsafe { self.inner.notify_one() } } /// Wakes up all blocked threads on this condvar. /// /// See `Condvar::notify_all`. - #[unstable(feature = "std_misc", + #[unstable(feature = "static_condvar", reason = "may be merged with Condvar in the future")] pub fn notify_all(&'static self) { unsafe { self.inner.notify_all() } } @@ -318,7 +359,7 @@ impl StaticCondvar { /// active users of the condvar, and this also doesn't prevent any future /// users of the condvar. This method is required to be called to not leak /// memory on all platforms. - #[unstable(feature = "std_misc", + #[unstable(feature = "static_condvar", reason = "may be merged with Condvar in the future")] pub unsafe fn destroy(&'static self) { self.inner.destroy() @@ -447,7 +488,9 @@ mod tests { static S: AtomicUsize = ATOMIC_USIZE_INIT; let g = M.lock().unwrap(); - let (g, success) = C.wait_timeout_with(g, Duration::nanoseconds(1000), |_| false).unwrap(); + let (g, success) = C.wait_timeout_with(g, Duration::new(0, 1000), |_| { + false + }).unwrap(); assert!(!success); let (tx, rx) = channel(); @@ -471,7 +514,8 @@ mod tests { }); let mut state = 0; - let (_g, success) = C.wait_timeout_with(g, Duration::days(1), |_| { + let day = 24 * 60 * 60; + let (_g, success) = C.wait_timeout_with(g, Duration::new(day, 0), |_| { assert_eq!(state, S.load(Ordering::SeqCst)); tx.send(()).unwrap(); state += 1; diff --git a/src/libstd/sys/unix/condvar.rs b/src/libstd/sys/unix/condvar.rs index ed6382e000ac9..29a13cc6be731 100644 --- a/src/libstd/sys/unix/condvar.rs +++ b/src/libstd/sys/unix/condvar.rs @@ -57,25 +57,20 @@ impl Condvar { // https://github.com/llvm-mirror/libcxx/blob/release_35/src/condition_variable.cpp#L46 // https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367 pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { - if dur <= Duration::zero() { - return false; - } - - // First, figure out what time it currently is, in both system and stable time. - // pthread_cond_timedwait uses system time, but we want to report timeout based on stable - // time. + // First, figure out what time it currently is, in both system and + // stable time. pthread_cond_timedwait uses system time, but we want to + // report timeout based on stable time. let mut sys_now = libc::timeval { tv_sec: 0, tv_usec: 0 }; let stable_now = time::SteadyTime::now(); let r = ffi::gettimeofday(&mut sys_now, ptr::null_mut()); debug_assert_eq!(r, 0); - let seconds = dur.num_seconds() as libc::time_t; + let seconds = dur.secs() as libc::time_t; let timeout = match sys_now.tv_sec.checked_add(seconds) { Some(sec) => { libc::timespec { tv_sec: sec, - tv_nsec: (dur - Duration::seconds(dur.num_seconds())) - .num_nanoseconds().unwrap() as libc::c_long, + tv_nsec: dur.extra_nanos() as libc::c_long, } } None => { @@ -87,11 +82,12 @@ impl Condvar { }; // And wait! - let r = ffi::pthread_cond_timedwait(self.inner.get(), mutex::raw(mutex), &timeout); + let r = ffi::pthread_cond_timedwait(self.inner.get(), mutex::raw(mutex), + &timeout); debug_assert!(r == libc::ETIMEDOUT || r == 0); - // ETIMEDOUT is not a totally reliable method of determining timeout due to clock shifts, - // so do the check ourselves + // ETIMEDOUT is not a totally reliable method of determining timeout due + // to clock shifts, so do the check ourselves &time::SteadyTime::now() - &stable_now < dur } diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index cfab9d1c51a15..0cb5a06e6b62f 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -129,14 +129,9 @@ impl Thread { } pub fn sleep(dur: Duration) { - if dur < Duration::zero() { - return Thread::yield_now() - } - let seconds = dur.num_seconds(); - let ns = dur - Duration::seconds(seconds); let mut ts = libc::timespec { - tv_sec: seconds as libc::time_t, - tv_nsec: ns.num_nanoseconds().unwrap() as libc::c_long, + tv_sec: dur.secs() as libc::time_t, + tv_nsec: dur.extra_nanos() as libc::c_long, }; // If we're awoken with a signal then the return value will be -1 and diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs index f59eb2c03013f..16dfd3eebd02e 100644 --- a/src/libstd/sys/unix/time.rs +++ b/src/libstd/sys/unix/time.rs @@ -10,12 +10,15 @@ pub use self::inner::SteadyTime; +const NSEC_PER_SEC: u64 = 1_000_000_000; + #[cfg(any(target_os = "macos", target_os = "ios"))] mod inner { use libc; use time::Duration; use ops::Sub; use sync::{Once, ONCE_INIT}; + use super::NSEC_PER_SEC; pub struct SteadyTime { t: u64 @@ -32,11 +35,6 @@ mod inner { t: unsafe { mach_absolute_time() }, } } - - pub fn ns(&self) -> u64 { - let info = info(); - self.t * info.numer as u64 / info.denom as u64 - } } fn info() -> &'static libc::mach_timebase_info { @@ -59,8 +57,9 @@ mod inner { fn sub(self, other: &SteadyTime) -> Duration { let info = info(); - let diff = self.t as i64 - other.t as i64; - Duration::nanoseconds(diff * info.numer as i64 / info.denom as i64) + let diff = self.t as u64 - other.t as u64; + let nanos = diff * info.numer as u64 / info.denom as u64; + Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32) } } } @@ -70,8 +69,7 @@ mod inner { use libc; use time::Duration; use ops::Sub; - - const NSEC_PER_SEC: i64 = 1_000_000_000; + use super::NSEC_PER_SEC; pub struct SteadyTime { t: libc::timespec, @@ -104,10 +102,6 @@ mod inner { } t } - - pub fn ns(&self) -> u64 { - self.t.tv_sec as u64 * NSEC_PER_SEC as u64 + self.t.tv_nsec as u64 - } } impl<'a> Sub for &'a SteadyTime { @@ -115,12 +109,12 @@ mod inner { fn sub(self, other: &SteadyTime) -> Duration { if self.t.tv_nsec >= other.t.tv_nsec { - Duration::seconds(self.t.tv_sec as i64 - other.t.tv_sec as i64) + - Duration::nanoseconds(self.t.tv_nsec as i64 - other.t.tv_nsec as i64) + Duration::new(self.t.tv_sec as u64 - other.t.tv_sec as u64, + self.t.tv_nsec as u32 - other.t.tv_nsec as u32) } else { - Duration::seconds(self.t.tv_sec as i64 - 1 - other.t.tv_sec as i64) + - Duration::nanoseconds(self.t.tv_nsec as i64 + NSEC_PER_SEC - - other.t.tv_nsec as i64) + Duration::new(self.t.tv_sec as u64 - 1 - other.t.tv_sec as u64, + self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) - + other.t.tv_nsec as u32) } } } diff --git a/src/libstd/sys/windows/condvar.rs b/src/libstd/sys/windows/condvar.rs index 67552255fdbeb..8bb2326e4d6b9 100644 --- a/src/libstd/sys/windows/condvar.rs +++ b/src/libstd/sys/windows/condvar.rs @@ -42,7 +42,7 @@ impl Condvar { pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { let r = ffi::SleepConditionVariableSRW(self.inner.get(), mutex::raw(mutex), - dur.num_milliseconds() as DWORD, + super::dur2timeout(dur), 0); if r == 0 { const ERROR_TIMEOUT: DWORD = 0x5B4; diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 4c30f0f86604f..6b7bff2c1c6f8 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -20,6 +20,7 @@ use libc; use num::Zero; use os::windows::ffi::{OsStrExt, OsStringExt}; use path::PathBuf; +use time::Duration; pub mod backtrace; pub mod c; @@ -151,6 +152,27 @@ fn cvt(i: I) -> io::Result { } } +fn dur2timeout(dur: Duration) -> libc::DWORD { + // Note that a duration is a (u64, u32) (seconds, nanoseconds) pair, and the + // timeouts in windows APIs are typically u32 milliseconds. To translate, we + // have two pieces to take care of: + // + // * Nanosecond precision is rounded up + // * Greater than u32::MAX milliseconds (50 days) is rounded up to INFINITE + // (never time out). + dur.secs().checked_mul(1000).and_then(|ms| { + ms.checked_add((dur.extra_nanos() as u64) / 1_000_000) + }).and_then(|ms| { + ms.checked_add(if dur.extra_nanos() % 1_000_000 > 0 {1} else {0}) + }).map(|ms| { + if ms > ::max_value() as u64 { + libc::INFINITE + } else { + ms as libc::DWORD + } + }).unwrap_or(libc::INFINITE) +} + fn ms_to_filetime(ms: u64) -> libc::FILETIME { // A FILETIME is a count of 100 nanosecond intervals, so we multiply by // 10000 b/c there are 10000 intervals in 1 ms diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index 797f45f8702e7..50dfee4ab1011 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -80,15 +80,7 @@ impl Thread { pub fn sleep(dur: Duration) { unsafe { - if dur < Duration::zero() { - return Thread::yield_now() - } - let ms = dur.num_milliseconds(); - // if we have a fractional number of milliseconds then add an extra - // millisecond to sleep for - let extra = dur - Duration::milliseconds(ms); - let ms = ms + if extra.is_zero() {0} else {1}; - c::Sleep(ms as DWORD); + c::Sleep(super::dur2timeout(dur)) } } } diff --git a/src/libstd/sys/windows/time.rs b/src/libstd/sys/windows/time.rs index 209460df10b7c..e64df54a0fa03 100644 --- a/src/libstd/sys/windows/time.rs +++ b/src/libstd/sys/windows/time.rs @@ -12,7 +12,7 @@ use ops::Sub; use time::Duration; use sync::{Once, ONCE_INIT}; -const NANOS_PER_SEC: i64 = 1_000_000_000; +const NANOS_PER_SEC: u64 = 1_000_000_000; pub struct SteadyTime { t: libc::LARGE_INTEGER, @@ -24,10 +24,6 @@ impl SteadyTime { unsafe { libc::QueryPerformanceCounter(&mut t.t); } t } - - pub fn ns(&self) -> u64 { - mul_div_i64(self.t as i64, NANOS_PER_SEC, frequency() as i64) as u64 - } } fn frequency() -> libc::LARGE_INTEGER { @@ -46,15 +42,16 @@ impl<'a> Sub for &'a SteadyTime { type Output = Duration; fn sub(self, other: &SteadyTime) -> Duration { - let diff = self.t as i64 - other.t as i64; - Duration::nanoseconds(mul_div_i64(diff, NANOS_PER_SEC, frequency() as i64)) + let diff = self.t as u64 - other.t as u64; + let nanos = mul_div_u64(diff, NANOS_PER_SEC, frequency() as u64); + Duration::new(nanos / NANOS_PER_SEC, (nanos % NANOS_PER_SEC) as u32) } } // Computes (value*numer)/denom without overflow, as long as both // (numer*denom) and the overall result fit into i64 (which is the case // for our time conversions). -fn mul_div_i64(value: i64, numer: i64, denom: i64) -> i64 { +fn mul_div_u64(value: u64, numer: u64, denom: u64) -> u64 { let q = value / denom; let r = value % denom; // Decompose value as (value/denom*denom + value%denom), @@ -65,9 +62,6 @@ fn mul_div_i64(value: i64, numer: i64, denom: i64) -> i64 { #[test] fn test_muldiv() { - assert_eq!(mul_div_i64( 1_000_000_000_001, 1_000_000_000, 1_000_000), 1_000_000_000_001_000); - assert_eq!(mul_div_i64(-1_000_000_000_001, 1_000_000_000, 1_000_000), -1_000_000_000_001_000); - assert_eq!(mul_div_i64(-1_000_000_000_001,-1_000_000_000, 1_000_000), 1_000_000_000_001_000); - assert_eq!(mul_div_i64( 1_000_000_000_001, 1_000_000_000,-1_000_000), -1_000_000_000_001_000); - assert_eq!(mul_div_i64( 1_000_000_000_001,-1_000_000_000,-1_000_000), 1_000_000_000_001_000); + assert_eq!(mul_div_u64( 1_000_000_000_001, 1_000_000_000, 1_000_000), + 1_000_000_000_001_000); } diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index f480147b93ee7..7c8cb5b01c108 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -482,7 +482,23 @@ pub fn catch_panic(f: F) -> Result /// spurious wakeup. #[stable(feature = "rust1", since = "1.0.0")] pub fn sleep_ms(ms: u32) { - imp::Thread::sleep(Duration::milliseconds(ms as i64)) + sleep(Duration::from_millis(ms as u64)) +} + +/// Puts the current thread to sleep for the specified amount of time. +/// +/// The thread may sleep longer than the duration specified due to scheduling +/// specifics or platform-dependent functionality. +/// +/// # Platform behavior +/// +/// On Unix platforms this function will not return early due to a +/// signal being received or a spurious wakeup. Platforms which do not support +/// nanosecond precision for sleeping will have `dur` rounded up to the nearest +/// granularity of time they can sleep for. +#[unstable(feature = "thread_sleep", reason = "waiting on Duration")] +pub fn sleep(dur: Duration) { + imp::Thread::sleep(dur) } /// Blocks unless or until the current thread's token is made available (may wake spuriously). @@ -508,18 +524,38 @@ pub fn park() { /// the specified duration has been reached (may wake spuriously). /// /// The semantics of this function are equivalent to `park()` except that the -/// thread will be blocked for roughly no longer than *duration*. This method +/// thread will be blocked for roughly no longer than *ms*. This method /// should not be used for precise timing due to anomalies such as /// preemption or platform differences that may not cause the maximum -/// amount of time waited to be precisely *duration* long. +/// amount of time waited to be precisely *ms* long. /// /// See the module doc for more detail. #[stable(feature = "rust1", since = "1.0.0")] pub fn park_timeout_ms(ms: u32) { + park_timeout(Duration::from_millis(ms as u64)) +} + +/// Blocks unless or until the current thread's token is made available or +/// the specified duration has been reached (may wake spuriously). +/// +/// The semantics of this function are equivalent to `park()` except that the +/// thread will be blocked for roughly no longer than *dur*. This method +/// should not be used for precise timing due to anomalies such as +/// preemption or platform differences that may not cause the maximum +/// amount of time waited to be precisely *dur* long. +/// +/// See the module doc for more detail. +/// +/// # Platform behavior +/// +/// Platforms which do not support nanosecond precision for sleeping will have +/// `dur` rounded up to the nearest granularity of time they can sleep for. +#[unstable(feature = "park_timeout", reason = "waiting on Duration")] +pub fn park_timeout(dur: Duration) { let thread = current(); let mut guard = thread.inner.lock.lock().unwrap(); if !*guard { - let (g, _) = thread.inner.cvar.wait_timeout_ms(guard, ms).unwrap(); + let (g, _) = thread.inner.cvar.wait_timeout(guard, dur).unwrap(); guard = g; } *guard = false; diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs index 636a0dd697a2b..8001df29d1fc7 100644 --- a/src/libstd/time/duration.rs +++ b/src/libstd/time/duration.rs @@ -10,589 +10,265 @@ //! Temporal quantification -#![unstable(feature = "std_misc")] +#![unstable(feature = "duration", reason = "recently added API per RFC 1040")] use prelude::v1::*; -use {fmt, i64}; -use ops::{Add, Sub, Mul, Div, Neg}; - -/// The number of nanoseconds in a microsecond. -const NANOS_PER_MICRO: i32 = 1000; -/// The number of nanoseconds in a millisecond. -const NANOS_PER_MILLI: i32 = 1000_000; -/// The number of nanoseconds in seconds. -const NANOS_PER_SEC: i32 = 1_000_000_000; -/// The number of microseconds per second. -const MICROS_PER_SEC: i64 = 1000_000; -/// The number of milliseconds per second. -const MILLIS_PER_SEC: i64 = 1000; -/// The number of seconds in a minute. -const SECS_PER_MINUTE: i64 = 60; -/// The number of seconds in an hour. -const SECS_PER_HOUR: i64 = 3600; -/// The number of (non-leap) seconds in days. -const SECS_PER_DAY: i64 = 86400; -/// The number of (non-leap) seconds in a week. -const SECS_PER_WEEK: i64 = 604800; - -macro_rules! try_opt { - ($e:expr) => (match $e { Some(v) => v, None => return None }) -} - - -/// ISO 8601 time duration with nanosecond precision. -/// This also allows for the negative duration; see individual methods for details. -#[unstable(feature = "std_misc")] +use fmt; +use ops::{Add, Sub, Mul, Div}; +use sys::time::SteadyTime; + +const NANOS_PER_SEC: u32 = 1_000_000_000; +const NANOS_PER_MILLI: u32 = 1_000_000; +const MILLIS_PER_SEC: u64 = 1_000; + +/// A duration type to represent a span of time, typically used for system +/// timeouts. +/// +/// Each duration is composed of a number of seconds and nanosecond precision. +/// APIs binding a system timeout will typically round up the nanosecond +/// precision if the underlying system does not support that level of precision. +/// +/// Durations implement many common traits, including `Add`, `Sub`, and other +/// ops traits. Currently a duration may only be inspected for its number of +/// seconds and its nanosecond precision. +/// +/// # Examples +/// +/// ``` +/// #![feature(duration)] +/// use std::time::Duration; +/// +/// let five_seconds = Duration::new(5, 0); +/// let five_seconds_and_five_nanos = five_seconds + Duration::new(0, 5); +/// +/// assert_eq!(five_seconds_and_five_nanos.secs(), 5); +/// assert_eq!(five_seconds_and_five_nanos.extra_nanos(), 5); +/// +/// let ten_millis = Duration::from_millis(10); +/// ``` #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)] pub struct Duration { - secs: i64, - nanos: i32, // Always 0 <= nanos < NANOS_PER_SEC + secs: u64, + nanos: u32, // Always 0 <= nanos < NANOS_PER_SEC } -/// The minimum possible `Duration`: `i64::MIN` milliseconds. -#[unstable(feature = "std_misc")] -pub const MIN: Duration = Duration { - secs: i64::MIN / MILLIS_PER_SEC - 1, - nanos: NANOS_PER_SEC + (i64::MIN % MILLIS_PER_SEC) as i32 * NANOS_PER_MILLI -}; - -/// The maximum possible `Duration`: `i64::MAX` milliseconds. -#[unstable(feature = "std_misc")] -pub const MAX: Duration = Duration { - secs: i64::MAX / MILLIS_PER_SEC, - nanos: (i64::MAX % MILLIS_PER_SEC) as i32 * NANOS_PER_MILLI -}; - impl Duration { - /// Makes a new `Duration` with given number of weeks. - /// Equivalent to `Duration::seconds(weeks * 7 * 24 * 60 * 60)` with overflow checks. - /// Panics when the duration is out of bounds. - #[inline] - #[unstable(feature = "std_misc")] - pub fn weeks(weeks: i64) -> Duration { - let secs = weeks.checked_mul(SECS_PER_WEEK).expect("Duration::weeks out of bounds"); - Duration::seconds(secs) - } - - /// Makes a new `Duration` with given number of days. - /// Equivalent to `Duration::seconds(days * 24 * 60 * 60)` with overflow checks. - /// Panics when the duration is out of bounds. - #[inline] - #[unstable(feature = "std_misc")] - pub fn days(days: i64) -> Duration { - let secs = days.checked_mul(SECS_PER_DAY).expect("Duration::days out of bounds"); - Duration::seconds(secs) - } - - /// Makes a new `Duration` with given number of hours. - /// Equivalent to `Duration::seconds(hours * 60 * 60)` with overflow checks. - /// Panics when the duration is out of bounds. - #[inline] - #[unstable(feature = "std_misc")] - pub fn hours(hours: i64) -> Duration { - let secs = hours.checked_mul(SECS_PER_HOUR).expect("Duration::hours ouf of bounds"); - Duration::seconds(secs) - } - - /// Makes a new `Duration` with given number of minutes. - /// Equivalent to `Duration::seconds(minutes * 60)` with overflow checks. - /// Panics when the duration is out of bounds. - #[inline] - #[unstable(feature = "std_misc")] - pub fn minutes(minutes: i64) -> Duration { - let secs = minutes.checked_mul(SECS_PER_MINUTE).expect("Duration::minutes out of bounds"); - Duration::seconds(secs) - } - - /// Makes a new `Duration` with given number of seconds. - /// Panics when the duration is more than `i64::MAX` milliseconds - /// or less than `i64::MIN` milliseconds. - #[inline] - #[unstable(feature = "std_misc")] - pub fn seconds(seconds: i64) -> Duration { - let d = Duration { secs: seconds, nanos: 0 }; - if d < MIN || d > MAX { - panic!("Duration::seconds out of bounds"); - } - d - } - - /// Makes a new `Duration` with given number of milliseconds. - #[inline] - #[unstable(feature = "std_misc")] - pub fn milliseconds(milliseconds: i64) -> Duration { - let (secs, millis) = div_mod_floor_64(milliseconds, MILLIS_PER_SEC); - let nanos = millis as i32 * NANOS_PER_MILLI; + /// Crates a new `Duration` from the specified number of seconds and + /// additional nanosecond precision. + /// + /// If the nanoseconds is greater than 1 billion (the number of nanoseconds + /// in a second), then it will carry over into the seconds provided. + pub fn new(secs: u64, nanos: u32) -> Duration { + let secs = secs + (nanos / NANOS_PER_SEC) as u64; + let nanos = nanos % NANOS_PER_SEC; Duration { secs: secs, nanos: nanos } } - /// Makes a new `Duration` with given number of microseconds. - #[inline] - #[unstable(feature = "std_misc")] - pub fn microseconds(microseconds: i64) -> Duration { - let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC); - let nanos = micros as i32 * NANOS_PER_MICRO; - Duration { secs: secs, nanos: nanos } - } - - /// Makes a new `Duration` with given number of nanoseconds. - #[inline] - #[unstable(feature = "std_misc")] - pub fn nanoseconds(nanos: i64) -> Duration { - let (secs, nanos) = div_mod_floor_64(nanos, NANOS_PER_SEC as i64); - Duration { secs: secs, nanos: nanos as i32 } - } - /// Runs a closure, returning the duration of time it took to run the /// closure. - #[unstable(feature = "std_misc")] + #[unstable(feature = "duration_span", + reason = "unsure if this is the right API or whether it should \ + wait for a more general \"moment in time\" \ + abstraction")] pub fn span(f: F) -> Duration where F: FnOnce() { - let before = super::precise_time_ns(); + let start = SteadyTime::now(); f(); - Duration::nanoseconds((super::precise_time_ns() - before) as i64) - } - - /// Returns the total number of whole weeks in the duration. - #[inline] - #[unstable(feature = "std_misc")] - pub fn num_weeks(&self) -> i64 { - self.num_days() / 7 - } - - /// Returns the total number of whole days in the duration. - #[unstable(feature = "std_misc")] - pub fn num_days(&self) -> i64 { - self.num_seconds() / SECS_PER_DAY - } - - /// Returns the total number of whole hours in the duration. - #[inline] - #[unstable(feature = "std_misc")] - pub fn num_hours(&self) -> i64 { - self.num_seconds() / SECS_PER_HOUR - } - - /// Returns the total number of whole minutes in the duration. - #[inline] - #[unstable(feature = "std_misc")] - pub fn num_minutes(&self) -> i64 { - self.num_seconds() / SECS_PER_MINUTE - } - - /// Returns the total number of whole seconds in the duration. - #[unstable(feature = "std_misc")] - pub fn num_seconds(&self) -> i64 { - // If secs is negative, nanos should be subtracted from the duration. - if self.secs < 0 && self.nanos > 0 { - self.secs + 1 - } else { - self.secs - } - } - - /// Returns the number of nanoseconds such that - /// `nanos_mod_sec() + num_seconds() * NANOS_PER_SEC` is the total number of - /// nanoseconds in the duration. - fn nanos_mod_sec(&self) -> i32 { - if self.secs < 0 && self.nanos > 0 { - self.nanos - NANOS_PER_SEC - } else { - self.nanos - } - } - - /// Returns the total number of whole milliseconds in the duration, - #[unstable(feature = "std_misc")] - pub fn num_milliseconds(&self) -> i64 { - // A proper Duration will not overflow, because MIN and MAX are defined - // such that the range is exactly i64 milliseconds. - let secs_part = self.num_seconds() * MILLIS_PER_SEC; - let nanos_part = self.nanos_mod_sec() / NANOS_PER_MILLI; - secs_part + nanos_part as i64 - } - - /// Returns the total number of whole microseconds in the duration, - /// or `None` on overflow (exceeding 2^63 microseconds in either direction). - #[unstable(feature = "std_misc")] - pub fn num_microseconds(&self) -> Option { - let secs_part = try_opt!(self.num_seconds().checked_mul(MICROS_PER_SEC)); - let nanos_part = self.nanos_mod_sec() / NANOS_PER_MICRO; - secs_part.checked_add(nanos_part as i64) + &SteadyTime::now() - &start } - /// Returns the total number of whole nanoseconds in the duration, - /// or `None` on overflow (exceeding 2^63 nanoseconds in either direction). - #[unstable(feature = "std_misc")] - pub fn num_nanoseconds(&self) -> Option { - let secs_part = try_opt!(self.num_seconds().checked_mul(NANOS_PER_SEC as i64)); - let nanos_part = self.nanos_mod_sec(); - secs_part.checked_add(nanos_part as i64) + /// Creates a new `Duration` from the specified number of seconds. + pub fn from_secs(secs: u64) -> Duration { + Duration { secs: secs, nanos: 0 } } - /// Add two durations, returning `None` if overflow occurred. - #[unstable(feature = "std_misc")] - pub fn checked_add(&self, rhs: &Duration) -> Option { - let mut secs = try_opt!(self.secs.checked_add(rhs.secs)); - let mut nanos = self.nanos + rhs.nanos; - if nanos >= NANOS_PER_SEC { - nanos -= NANOS_PER_SEC; - secs = try_opt!(secs.checked_add(1)); - } - let d = Duration { secs: secs, nanos: nanos }; - // Even if d is within the bounds of i64 seconds, - // it might still overflow i64 milliseconds. - if d < MIN || d > MAX { None } else { Some(d) } - } - - /// Subtract two durations, returning `None` if overflow occurred. - #[unstable(feature = "std_misc")] - pub fn checked_sub(&self, rhs: &Duration) -> Option { - let mut secs = try_opt!(self.secs.checked_sub(rhs.secs)); - let mut nanos = self.nanos - rhs.nanos; - if nanos < 0 { - nanos += NANOS_PER_SEC; - secs = try_opt!(secs.checked_sub(1)); - } - let d = Duration { secs: secs, nanos: nanos }; - // Even if d is within the bounds of i64 seconds, - // it might still overflow i64 milliseconds. - if d < MIN || d > MAX { None } else { Some(d) } - } - - /// The minimum possible `Duration`: `i64::MIN` milliseconds. - #[inline] - #[unstable(feature = "std_misc")] - pub fn min_value() -> Duration { MIN } - - /// The maximum possible `Duration`: `i64::MAX` milliseconds. - #[inline] - #[unstable(feature = "std_misc")] - pub fn max_value() -> Duration { MAX } - - /// A duration where the stored seconds and nanoseconds are equal to zero. - #[inline] - #[unstable(feature = "std_misc")] - pub fn zero() -> Duration { - Duration { secs: 0, nanos: 0 } - } - - /// Returns `true` if the duration equals `Duration::zero()`. - #[inline] - #[unstable(feature = "std_misc")] - pub fn is_zero(&self) -> bool { - self.secs == 0 && self.nanos == 0 + /// Creates a new `Duration` from the specified number of milliseconds. + pub fn from_millis(millis: u64) -> Duration { + let secs = millis / MILLIS_PER_SEC; + let nanos = ((millis % MILLIS_PER_SEC) as u32) * NANOS_PER_MILLI; + Duration { secs: secs, nanos: nanos } } -} -#[unstable(feature = "std_misc")] -impl Neg for Duration { - type Output = Duration; + /// Returns the number of whole seconds represented by this duration. + /// + /// The extra precision represented by this duration is ignored (e.g. extra + /// nanoseconds are not represented in the returned value). + pub fn secs(&self) -> u64 { self.secs } - #[inline] - fn neg(self) -> Duration { - if self.nanos == 0 { - Duration { secs: -self.secs, nanos: 0 } - } else { - Duration { secs: -self.secs - 1, nanos: NANOS_PER_SEC - self.nanos } - } - } + /// Returns the nanosecond precision represented by this duration. + /// + /// This method does **not** return the length of the duration when + /// represented by nanoseconds. The returned number always represents a + /// fractional portion of a second (e.g. it is less than one billion). + pub fn extra_nanos(&self) -> u32 { self.nanos } } -#[unstable(feature = "std_misc")] impl Add for Duration { type Output = Duration; fn add(self, rhs: Duration) -> Duration { - let mut secs = self.secs + rhs.secs; + let mut secs = self.secs.checked_add(rhs.secs) + .expect("overflow when adding durations"); let mut nanos = self.nanos + rhs.nanos; if nanos >= NANOS_PER_SEC { nanos -= NANOS_PER_SEC; - secs += 1; + secs = secs.checked_add(1).expect("overflow when adding durations"); } + debug_assert!(nanos < NANOS_PER_SEC); Duration { secs: secs, nanos: nanos } } } -#[unstable(feature = "std_misc")] impl Sub for Duration { type Output = Duration; fn sub(self, rhs: Duration) -> Duration { - let mut secs = self.secs - rhs.secs; - let mut nanos = self.nanos - rhs.nanos; - if nanos < 0 { - nanos += NANOS_PER_SEC; - secs -= 1; - } + let mut secs = self.secs.checked_sub(rhs.secs) + .expect("overflow when subtracting durations"); + let nanos = if self.nanos >= rhs.nanos { + self.nanos - rhs.nanos + } else { + secs = secs.checked_sub(1) + .expect("overflow when subtracting durations"); + self.nanos + NANOS_PER_SEC - rhs.nanos + }; + debug_assert!(nanos < NANOS_PER_SEC); Duration { secs: secs, nanos: nanos } } } -#[unstable(feature = "std_misc")] -impl Mul for Duration { +impl Mul for Duration { type Output = Duration; - fn mul(self, rhs: i32) -> Duration { - // Multiply nanoseconds as i64, because it cannot overflow that way. - let total_nanos = self.nanos as i64 * rhs as i64; - let (extra_secs, nanos) = div_mod_floor_64(total_nanos, NANOS_PER_SEC as i64); - let secs = self.secs * rhs as i64 + extra_secs; - Duration { secs: secs, nanos: nanos as i32 } + fn mul(self, rhs: u32) -> Duration { + // Multiply nanoseconds as u64, because it cannot overflow that way. + let total_nanos = self.nanos as u64 * rhs as u64; + let extra_secs = total_nanos / (NANOS_PER_SEC as u64); + let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32; + let secs = self.secs.checked_mul(rhs as u64) + .and_then(|s| s.checked_add(extra_secs)) + .expect("overflow when multiplying duration"); + debug_assert!(nanos < NANOS_PER_SEC); + Duration { secs: secs, nanos: nanos } } } -#[unstable(feature = "std_misc")] -impl Div for Duration { +impl Div for Duration { type Output = Duration; - fn div(self, rhs: i32) -> Duration { - let mut secs = self.secs / rhs as i64; - let carry = self.secs - secs * rhs as i64; - let extra_nanos = carry * NANOS_PER_SEC as i64 / rhs as i64; - let mut nanos = self.nanos / rhs + extra_nanos as i32; - if nanos >= NANOS_PER_SEC { - nanos -= NANOS_PER_SEC; - secs += 1; - } - if nanos < 0 { - nanos += NANOS_PER_SEC; - secs -= 1; - } + fn div(self, rhs: u32) -> Duration { + let secs = self.secs / (rhs as u64); + let carry = self.secs - secs * (rhs as u64); + let extra_nanos = carry * (NANOS_PER_SEC as u64) / (rhs as u64); + let nanos = self.nanos / rhs + (extra_nanos as u32); + debug_assert!(nanos < NANOS_PER_SEC); Duration { secs: secs, nanos: nanos } } } -#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for Duration { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // technically speaking, negative duration is not valid ISO 8601, - // but we need to print it anyway. - let (abs, sign) = if self.secs < 0 { (-*self, "-") } else { (*self, "") }; - - let days = abs.secs / SECS_PER_DAY; - let secs = abs.secs - days * SECS_PER_DAY; - let hasdate = days != 0; - let hastime = (secs != 0 || abs.nanos != 0) || !hasdate; - - try!(write!(f, "{}P", sign)); - - if hasdate { - try!(write!(f, "{}D", days)); - } - if hastime { - if abs.nanos == 0 { - try!(write!(f, "T{}S", secs)); - } else if abs.nanos % NANOS_PER_MILLI == 0 { - try!(write!(f, "T{}.{:03}S", secs, abs.nanos / NANOS_PER_MILLI)); - } else if abs.nanos % NANOS_PER_MICRO == 0 { - try!(write!(f, "T{}.{:06}S", secs, abs.nanos / NANOS_PER_MICRO)); - } else { - try!(write!(f, "T{}.{:09}S", secs, abs.nanos)); - } + match (self.secs, self.nanos) { + (s, 0) => write!(f, "{}s", s), + (0, n) if n % NANOS_PER_MILLI == 0 => write!(f, "{}ms", + n / NANOS_PER_MILLI), + (0, n) if n % 1_000 == 0 => write!(f, "{}µs", n / 1_000), + (0, n) => write!(f, "{}ns", n), + (s, n) => write!(f, "{}.{}s", s, + format!("{:09}", n).trim_right_matches('0')) } - Ok(()) - } -} - -// Copied from libnum -#[inline] -fn div_mod_floor_64(this: i64, other: i64) -> (i64, i64) { - (div_floor_64(this, other), mod_floor_64(this, other)) -} - -#[inline] -fn div_floor_64(this: i64, other: i64) -> i64 { - match div_rem_64(this, other) { - (d, r) if (r > 0 && other < 0) - || (r < 0 && other > 0) => d - 1, - (d, _) => d, - } -} - -#[inline] -fn mod_floor_64(this: i64, other: i64) -> i64 { - match this % other { - r if (r > 0 && other < 0) - || (r < 0 && other > 0) => r + other, - r => r, } } -#[inline] -fn div_rem_64(this: i64, other: i64) -> (i64, i64) { - (this / other, this % other) -} - #[cfg(test)] mod tests { - use super::{Duration, MIN, MAX}; - use {i32, i64}; - use option::Option::{Some, None}; - use string::ToString; + use prelude::v1::*; + use super::Duration; #[test] - fn test_duration() { - assert!(Duration::seconds(1) != Duration::zero()); - assert_eq!(Duration::seconds(1) + Duration::seconds(2), Duration::seconds(3)); - assert_eq!(Duration::seconds(86399) + Duration::seconds(4), - Duration::days(1) + Duration::seconds(3)); - assert_eq!(Duration::days(10) - Duration::seconds(1000), Duration::seconds(863000)); - assert_eq!(Duration::days(10) - Duration::seconds(1000000), Duration::seconds(-136000)); - assert_eq!(Duration::days(2) + Duration::seconds(86399) + - Duration::nanoseconds(1234567890), - Duration::days(3) + Duration::nanoseconds(234567890)); - assert_eq!(-Duration::days(3), Duration::days(-3)); - assert_eq!(-(Duration::days(3) + Duration::seconds(70)), - Duration::days(-4) + Duration::seconds(86400-70)); + fn creation() { + assert!(Duration::from_secs(1) != Duration::from_secs(0)); + assert_eq!(Duration::from_secs(1) + Duration::from_secs(2), + Duration::from_secs(3)); + assert_eq!(Duration::from_millis(10) + Duration::from_secs(4), + Duration::new(4, 10 * 1_000_000)); + assert_eq!(Duration::from_millis(4000), Duration::new(4, 0)); } #[test] - fn test_duration_num_days() { - assert_eq!(Duration::zero().num_days(), 0); - assert_eq!(Duration::days(1).num_days(), 1); - assert_eq!(Duration::days(-1).num_days(), -1); - assert_eq!(Duration::seconds(86399).num_days(), 0); - assert_eq!(Duration::seconds(86401).num_days(), 1); - assert_eq!(Duration::seconds(-86399).num_days(), 0); - assert_eq!(Duration::seconds(-86401).num_days(), -1); - assert_eq!(Duration::days(i32::MAX as i64).num_days(), i32::MAX as i64); - assert_eq!(Duration::days(i32::MIN as i64).num_days(), i32::MIN as i64); + fn secs() { + assert_eq!(Duration::new(0, 0).secs(), 0); + assert_eq!(Duration::from_secs(1).secs(), 1); + assert_eq!(Duration::from_millis(999).secs(), 0); + assert_eq!(Duration::from_millis(1001).secs(), 1); } #[test] - fn test_duration_num_seconds() { - assert_eq!(Duration::zero().num_seconds(), 0); - assert_eq!(Duration::seconds(1).num_seconds(), 1); - assert_eq!(Duration::seconds(-1).num_seconds(), -1); - assert_eq!(Duration::milliseconds(999).num_seconds(), 0); - assert_eq!(Duration::milliseconds(1001).num_seconds(), 1); - assert_eq!(Duration::milliseconds(-999).num_seconds(), 0); - assert_eq!(Duration::milliseconds(-1001).num_seconds(), -1); + fn nanos() { + assert_eq!(Duration::new(0, 0).extra_nanos(), 0); + assert_eq!(Duration::new(0, 5).extra_nanos(), 5); + assert_eq!(Duration::new(0, 1_000_000_001).extra_nanos(), 1); + assert_eq!(Duration::from_secs(1).extra_nanos(), 0); + assert_eq!(Duration::from_millis(999).extra_nanos(), 999 * 1_000_000); + assert_eq!(Duration::from_millis(1001).extra_nanos(), 1 * 1_000_000); } #[test] - fn test_duration_num_milliseconds() { - assert_eq!(Duration::zero().num_milliseconds(), 0); - assert_eq!(Duration::milliseconds(1).num_milliseconds(), 1); - assert_eq!(Duration::milliseconds(-1).num_milliseconds(), -1); - assert_eq!(Duration::microseconds(999).num_milliseconds(), 0); - assert_eq!(Duration::microseconds(1001).num_milliseconds(), 1); - assert_eq!(Duration::microseconds(-999).num_milliseconds(), 0); - assert_eq!(Duration::microseconds(-1001).num_milliseconds(), -1); - assert_eq!(Duration::milliseconds(i64::MAX).num_milliseconds(), i64::MAX); - assert_eq!(Duration::milliseconds(i64::MIN).num_milliseconds(), i64::MIN); - assert_eq!(MAX.num_milliseconds(), i64::MAX); - assert_eq!(MIN.num_milliseconds(), i64::MIN); + fn add() { + assert_eq!(Duration::new(0, 0) + Duration::new(0, 1), + Duration::new(0, 1)); + assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001), + Duration::new(1, 1)); } #[test] - fn test_duration_num_microseconds() { - assert_eq!(Duration::zero().num_microseconds(), Some(0)); - assert_eq!(Duration::microseconds(1).num_microseconds(), Some(1)); - assert_eq!(Duration::microseconds(-1).num_microseconds(), Some(-1)); - assert_eq!(Duration::nanoseconds(999).num_microseconds(), Some(0)); - assert_eq!(Duration::nanoseconds(1001).num_microseconds(), Some(1)); - assert_eq!(Duration::nanoseconds(-999).num_microseconds(), Some(0)); - assert_eq!(Duration::nanoseconds(-1001).num_microseconds(), Some(-1)); - assert_eq!(Duration::microseconds(i64::MAX).num_microseconds(), Some(i64::MAX)); - assert_eq!(Duration::microseconds(i64::MIN).num_microseconds(), Some(i64::MIN)); - assert_eq!(MAX.num_microseconds(), None); - assert_eq!(MIN.num_microseconds(), None); - - // overflow checks - const MICROS_PER_DAY: i64 = 86400_000_000; - assert_eq!(Duration::days(i64::MAX / MICROS_PER_DAY).num_microseconds(), - Some(i64::MAX / MICROS_PER_DAY * MICROS_PER_DAY)); - assert_eq!(Duration::days(i64::MIN / MICROS_PER_DAY).num_microseconds(), - Some(i64::MIN / MICROS_PER_DAY * MICROS_PER_DAY)); - assert_eq!(Duration::days(i64::MAX / MICROS_PER_DAY + 1).num_microseconds(), None); - assert_eq!(Duration::days(i64::MIN / MICROS_PER_DAY - 1).num_microseconds(), None); + fn sub() { + assert_eq!(Duration::new(0, 1) - Duration::new(0, 0), + Duration::new(0, 1)); + assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000), + Duration::new(0, 1)); + assert_eq!(Duration::new(1, 0) - Duration::new(0, 1), + Duration::new(0, 999_999_999)); } - #[test] - fn test_duration_num_nanoseconds() { - assert_eq!(Duration::zero().num_nanoseconds(), Some(0)); - assert_eq!(Duration::nanoseconds(1).num_nanoseconds(), Some(1)); - assert_eq!(Duration::nanoseconds(-1).num_nanoseconds(), Some(-1)); - assert_eq!(Duration::nanoseconds(i64::MAX).num_nanoseconds(), Some(i64::MAX)); - assert_eq!(Duration::nanoseconds(i64::MIN).num_nanoseconds(), Some(i64::MIN)); - assert_eq!(MAX.num_nanoseconds(), None); - assert_eq!(MIN.num_nanoseconds(), None); - - // overflow checks - const NANOS_PER_DAY: i64 = 86400_000_000_000; - assert_eq!(Duration::days(i64::MAX / NANOS_PER_DAY).num_nanoseconds(), - Some(i64::MAX / NANOS_PER_DAY * NANOS_PER_DAY)); - assert_eq!(Duration::days(i64::MIN / NANOS_PER_DAY).num_nanoseconds(), - Some(i64::MIN / NANOS_PER_DAY * NANOS_PER_DAY)); - assert_eq!(Duration::days(i64::MAX / NANOS_PER_DAY + 1).num_nanoseconds(), None); - assert_eq!(Duration::days(i64::MIN / NANOS_PER_DAY - 1).num_nanoseconds(), None); + #[test] #[should_panic] + fn sub_bad1() { + Duration::new(0, 0) - Duration::new(0, 1); } - #[test] - fn test_duration_checked_ops() { - assert_eq!(Duration::milliseconds(i64::MAX - 1).checked_add(&Duration::microseconds(999)), - Some(Duration::milliseconds(i64::MAX - 2) + Duration::microseconds(1999))); - assert!(Duration::milliseconds(i64::MAX).checked_add(&Duration::microseconds(1000)) - .is_none()); - - assert_eq!(Duration::milliseconds(i64::MIN).checked_sub(&Duration::milliseconds(0)), - Some(Duration::milliseconds(i64::MIN))); - assert!(Duration::milliseconds(i64::MIN).checked_sub(&Duration::milliseconds(1)) - .is_none()); + #[test] #[should_panic] + fn sub_bad2() { + Duration::new(0, 0) - Duration::new(1, 0); } #[test] - fn test_duration_mul() { - assert_eq!(Duration::zero() * i32::MAX, Duration::zero()); - assert_eq!(Duration::zero() * i32::MIN, Duration::zero()); - assert_eq!(Duration::nanoseconds(1) * 0, Duration::zero()); - assert_eq!(Duration::nanoseconds(1) * 1, Duration::nanoseconds(1)); - assert_eq!(Duration::nanoseconds(1) * 1_000_000_000, Duration::seconds(1)); - assert_eq!(Duration::nanoseconds(1) * -1_000_000_000, -Duration::seconds(1)); - assert_eq!(-Duration::nanoseconds(1) * 1_000_000_000, -Duration::seconds(1)); - assert_eq!(Duration::nanoseconds(30) * 333_333_333, - Duration::seconds(10) - Duration::nanoseconds(10)); - assert_eq!((Duration::nanoseconds(1) + Duration::seconds(1) + Duration::days(1)) * 3, - Duration::nanoseconds(3) + Duration::seconds(3) + Duration::days(3)); - assert_eq!(Duration::milliseconds(1500) * -2, Duration::seconds(-3)); - assert_eq!(Duration::milliseconds(-1500) * 2, Duration::seconds(-3)); + fn mul() { + assert_eq!(Duration::new(0, 1) * 2, Duration::new(0, 2)); + assert_eq!(Duration::new(1, 1) * 3, Duration::new(3, 3)); + assert_eq!(Duration::new(0, 500_000_001) * 4, Duration::new(2, 4)); + assert_eq!(Duration::new(0, 500_000_001) * 4000, + Duration::new(2000, 4000)); } #[test] - fn test_duration_div() { - assert_eq!(Duration::zero() / i32::MAX, Duration::zero()); - assert_eq!(Duration::zero() / i32::MIN, Duration::zero()); - assert_eq!(Duration::nanoseconds(123_456_789) / 1, Duration::nanoseconds(123_456_789)); - assert_eq!(Duration::nanoseconds(123_456_789) / -1, -Duration::nanoseconds(123_456_789)); - assert_eq!(-Duration::nanoseconds(123_456_789) / -1, Duration::nanoseconds(123_456_789)); - assert_eq!(-Duration::nanoseconds(123_456_789) / 1, -Duration::nanoseconds(123_456_789)); - assert_eq!(Duration::seconds(1) / 3, Duration::nanoseconds(333_333_333)); - assert_eq!(Duration::seconds(4) / 3, Duration::nanoseconds(1_333_333_333)); - assert_eq!(Duration::seconds(-1) / 2, Duration::milliseconds(-500)); - assert_eq!(Duration::seconds(1) / -2, Duration::milliseconds(-500)); - assert_eq!(Duration::seconds(-1) / -2, Duration::milliseconds(500)); - assert_eq!(Duration::seconds(-4) / 3, Duration::nanoseconds(-1_333_333_333)); - assert_eq!(Duration::seconds(-4) / -3, Duration::nanoseconds(1_333_333_333)); + fn div() { + assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0)); + assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333)); + assert_eq!(Duration::new(99, 999_999_000) / 100, + Duration::new(0, 999_999_990)); } #[test] - fn test_duration_fmt() { - assert_eq!(Duration::zero().to_string(), "PT0S"); - assert_eq!(Duration::days(42).to_string(), "P42D"); - assert_eq!(Duration::days(-42).to_string(), "-P42D"); - assert_eq!(Duration::seconds(42).to_string(), "PT42S"); - assert_eq!(Duration::milliseconds(42).to_string(), "PT0.042S"); - assert_eq!(Duration::microseconds(42).to_string(), "PT0.000042S"); - assert_eq!(Duration::nanoseconds(42).to_string(), "PT0.000000042S"); - assert_eq!((Duration::days(7) + Duration::milliseconds(6543)).to_string(), - "P7DT6.543S"); - assert_eq!(Duration::seconds(-86401).to_string(), "-P1DT1S"); - assert_eq!(Duration::nanoseconds(-1).to_string(), "-PT0.000000001S"); - - // the format specifier should have no effect on `Duration` - assert_eq!(format!("{:30}", Duration::days(1) + Duration::milliseconds(2345)), - "P1DT2.345S"); + fn display() { + assert_eq!(Duration::new(0, 2).to_string(), "2ns"); + assert_eq!(Duration::new(0, 2_000_000).to_string(), "2ms"); + assert_eq!(Duration::new(2, 0).to_string(), "2s"); + assert_eq!(Duration::new(2, 2).to_string(), "2.000000002s"); + assert_eq!(Duration::new(2, 2_000_000).to_string(), + "2.002s"); + assert_eq!(Duration::new(0, 2_000_002).to_string(), + "2000002ns"); + assert_eq!(Duration::new(2, 2_000_002).to_string(), + "2.002000002s"); } } diff --git a/src/libstd/time/mod.rs b/src/libstd/time/mod.rs index 4d9bb8050d31e..d535b19551995 100644 --- a/src/libstd/time/mod.rs +++ b/src/libstd/time/mod.rs @@ -10,17 +10,8 @@ //! Temporal quantification. -#![unstable(feature = "std_misc")] - -use sys::time::SteadyTime; +#![unstable(feature = "time")] pub use self::duration::Duration; -pub mod duration; - -/// Returns the current value of a high-resolution performance counter -/// in nanoseconds since an unspecified epoch. -// NB: this is intentionally not public, this is not ready to stabilize its api. -fn precise_time_ns() -> u64 { - SteadyTime::now().ns() -} +mod duration; diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 66ddd73101e26..0097bab2fea4d 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -506,7 +506,7 @@ fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan, match dst.registry.as_ref().and_then(|registry| registry.find_description(code)) { Some(_) => { try!(print_diagnostic(dst, &ss[..], Help, - &format!("pass `--explain {}` to see a detailed \ + &format!("run `rustc --explain {}` to see a detailed \ explanation", code), None)); } None => () diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 00ef8760985be..b16154861530d 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -43,6 +43,8 @@ #![feature(std_misc)] #![feature(libc)] #![feature(set_stdio)] +#![feature(duration)] +#![feature(duration_span)] extern crate getopts; extern crate serialize; @@ -1069,7 +1071,7 @@ impl Bencher { } pub fn ns_elapsed(&mut self) -> u64 { - self.dur.num_nanoseconds().unwrap() as u64 + self.dur.secs() * 1_000_000_000 + (self.dur.extra_nanos() as u64) } pub fn ns_per_iter(&mut self) -> u64 { @@ -1105,7 +1107,7 @@ impl Bencher { // (i.e. larger error bars). if n == 0 { n = 1; } - let mut total_run = Duration::nanoseconds(0); + let mut total_run = Duration::new(0, 0); let samples : &mut [f64] = &mut [0.0_f64; 50]; loop { let mut summ = None; @@ -1134,7 +1136,7 @@ impl Bencher { // If we've run for 100ms and seem to have converged to a // stable median. - if loop_run.num_milliseconds() > 100 && + if loop_run > Duration::from_millis(100) && summ.median_abs_dev_pct < 1.0 && summ.median - summ5.median < summ5.median_abs_dev { return summ5; @@ -1142,7 +1144,7 @@ impl Bencher { total_run = total_run + loop_run; // Longest we ever run for is 3s. - if total_run.num_seconds() > 3 { + if total_run > Duration::from_secs(3) { return summ5; } @@ -1166,7 +1168,7 @@ pub mod bench { pub fn benchmark(f: F) -> BenchSamples where F: FnMut(&mut Bencher) { let mut bs = Bencher { iterations: 0, - dur: Duration::nanoseconds(0), + dur: Duration::new(0, 0), bytes: 0 }; @@ -1185,7 +1187,7 @@ pub mod bench { pub fn run_once(f: F) where F: FnOnce(&mut Bencher) { let mut bs = Bencher { iterations: 0, - dur: Duration::nanoseconds(0), + dur: Duration::new(0, 0), bytes: 0 }; bs.bench_n(1, f); diff --git a/src/rustbook/build.rs b/src/rustbook/build.rs index f96704ee12832..47bdc9335c401 100644 --- a/src/rustbook/build.rs +++ b/src/rustbook/build.rs @@ -183,6 +183,12 @@ impl Subcommand for Build { tgt = PathBuf::from(&env::args().nth(3).unwrap()); } + // `_book` directory may already exist from previous runs. Check and + // delete it if it exists. + for entry in try!(fs::read_dir(&cwd)) { + let path = try!(entry).path(); + if path == tgt { try!(fs::remove_dir_all(&tgt)) } + } try!(fs::create_dir(&tgt)); try!(File::create(&tgt.join("rust-book.css")).and_then(|mut f| { diff --git a/src/test/auxiliary/crate-attributes-using-cfg_attr.rs b/src/test/auxiliary/crate-attributes-using-cfg_attr.rs new file mode 100644 index 0000000000000..0028b51f9d1ee --- /dev/null +++ b/src/test/auxiliary/crate-attributes-using-cfg_attr.rs @@ -0,0 +1,16 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// no-prefer-dynamic +// compile-flags: --cfg foo + +#![cfg_attr(foo, crate_type="lib")] + +pub fn foo() {} diff --git a/src/test/auxiliary/issue-9906.rs b/src/test/auxiliary/issue-9906.rs index 0da0b9fa47d6c..5eb48985bf90d 100644 --- a/src/test/auxiliary/issue-9906.rs +++ b/src/test/auxiliary/issue-9906.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:issue-9906.rs - pub use other::FooBar; pub use other::foo; diff --git a/src/test/auxiliary/issue_16723_multiple_items_syntax_ext.rs b/src/test/auxiliary/issue_16723_multiple_items_syntax_ext.rs index 58dee1216ee60..7be5c3cf47c70 100644 --- a/src/test/auxiliary/issue_16723_multiple_items_syntax_ext.rs +++ b/src/test/auxiliary/issue_16723_multiple_items_syntax_ext.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-stage1 // force-host #![feature(plugin_registrar, quote, rustc_private)] diff --git a/src/test/bench/core-map.rs b/src/test/bench/core-map.rs index 8f3e939f1f40d..af61b0aa0cdf4 100644 --- a/src/test/bench/core-map.rs +++ b/src/test/bench/core-map.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(std_misc, rand)] +#![feature(std_misc, rand, duration, duration_span)] use std::collections::{BTreeMap, HashMap, HashSet}; use std::env; diff --git a/src/test/bench/core-set.rs b/src/test/bench/core-set.rs index aeedaa288fef8..eebf6feaffac3 100644 --- a/src/test/bench/core-set.rs +++ b/src/test/bench/core-set.rs @@ -10,7 +10,7 @@ // ignore-pretty very bad with line comments -#![feature(unboxed_closures, rand, std_misc, collections)] +#![feature(unboxed_closures, rand, std_misc, collections, duration, duration_span)] extern crate collections; extern crate rand; @@ -167,13 +167,13 @@ fn write_results(label: &str, results: &Results) { fn empty_results() -> Results { Results { - sequential_ints: Duration::seconds(0), - random_ints: Duration::seconds(0), - delete_ints: Duration::seconds(0), + sequential_ints: Duration::new(0, 0), + random_ints: Duration::new(0, 0), + delete_ints: Duration::new(0, 0), - sequential_strings: Duration::seconds(0), - random_strings: Duration::seconds(0), - delete_strings: Duration::seconds(0), + sequential_strings: Duration::new(0, 0), + random_strings: Duration::new(0, 0), + delete_strings: Duration::new(0, 0), } } diff --git a/src/test/bench/core-std.rs b/src/test/bench/core-std.rs index 19f83c7817c7c..6e85abb8e149f 100644 --- a/src/test/bench/core-std.rs +++ b/src/test/bench/core-std.rs @@ -10,7 +10,7 @@ // Microbenchmarks for various functions in std and extra -#![feature(rand, collections, std_misc)] +#![feature(rand, collections, std_misc, duration, duration_span)] use std::iter::repeat; use std::mem::swap; @@ -52,7 +52,7 @@ fn maybe_run_test(argv: &[String], name: String, test: F) where F: FnOnce() { let dur = Duration::span(test); - println!("{}:\t\t{} ms", name, dur.num_milliseconds()); + println!("{}:\t\t{}", name, dur); } fn shift_push() { diff --git a/src/test/bench/msgsend-pipes-shared.rs b/src/test/bench/msgsend-pipes-shared.rs index c7748d59c6a04..2b7e204423e32 100644 --- a/src/test/bench/msgsend-pipes-shared.rs +++ b/src/test/bench/msgsend-pipes-shared.rs @@ -18,7 +18,7 @@ // different scalability characteristics compared to the select // version. -#![feature(std_misc)] +#![feature(duration, duration_span)] use std::sync::mpsc::{channel, Sender, Receiver}; use std::env; @@ -88,9 +88,9 @@ fn run(args: &[String]) { }); let result = result.unwrap(); print!("Count is {}\n", result); - print!("Test took {} ms\n", dur.num_milliseconds()); - let thruput = ((size / workers * workers) as f64) / (dur.num_milliseconds() as f64); - print!("Throughput={} per sec\n", thruput / 1000.0); + print!("Test took {}\n", dur); + let thruput = ((size / workers * workers) as f64) / (dur.secs() as f64); + print!("Throughput={} per sec\n", thruput); assert_eq!(result, num_bytes * size); } diff --git a/src/test/bench/msgsend-pipes.rs b/src/test/bench/msgsend-pipes.rs index b6a6e06088a09..5a541420d2abf 100644 --- a/src/test/bench/msgsend-pipes.rs +++ b/src/test/bench/msgsend-pipes.rs @@ -14,7 +14,7 @@ // // I *think* it's the same, more or less. -#![feature(std_misc)] +#![feature(duration, duration_span)] use std::sync::mpsc::{channel, Sender, Receiver}; use std::env; @@ -95,9 +95,9 @@ fn run(args: &[String]) { }); let result = result.unwrap(); print!("Count is {}\n", result); - print!("Test took {} ms\n", dur.num_milliseconds()); - let thruput = ((size / workers * workers) as f64) / (dur.num_milliseconds() as f64); - print!("Throughput={} per sec\n", thruput / 1000.0); + print!("Test took {}\n", dur); + let thruput = ((size / workers * workers) as f64) / (dur.secs() as f64); + print!("Throughput={} per sec\n", thruput); assert_eq!(result, num_bytes * size); } diff --git a/src/test/bench/msgsend-ring-mutex-arcs.rs b/src/test/bench/msgsend-ring-mutex-arcs.rs index 07174de88a3d0..93e3394097bc5 100644 --- a/src/test/bench/msgsend-ring-mutex-arcs.rs +++ b/src/test/bench/msgsend-ring-mutex-arcs.rs @@ -17,7 +17,7 @@ // no-pretty-expanded FIXME #15189 -#![feature(std_misc)] +#![feature(duration, duration_span, std_misc)] use std::env; use std::sync::{Arc, Future, Mutex, Condvar}; @@ -107,9 +107,9 @@ fn main() { // all done, report stats. let num_msgs = num_tasks * msg_per_task; - let rate = (num_msgs as f64) / (dur.num_milliseconds() as f64); + let rate = (num_msgs as f64) / (dur.secs() as f64); - println!("Sent {} messages in {} ms", num_msgs, dur.num_milliseconds()); - println!(" {} messages / second", rate / 1000.0); - println!(" {} μs / message", 1000000. / rate / 1000.0); + println!("Sent {} messages in {}", num_msgs, dur); + println!(" {} messages / second", rate); + println!(" {} μs / message", 1000000. / rate); } diff --git a/src/test/bench/shootout-pfib.rs b/src/test/bench/shootout-pfib.rs index ed20f4b6362ce..2d5aae30ae8a9 100644 --- a/src/test/bench/shootout-pfib.rs +++ b/src/test/bench/shootout-pfib.rs @@ -18,7 +18,7 @@ */ -#![feature(std_misc, rustc_private)] +#![feature(duration, duration_span, rustc_private)] extern crate getopts; diff --git a/src/test/bench/std-smallintmap.rs b/src/test/bench/std-smallintmap.rs index dd56b18c144f2..d7e556a124fe1 100644 --- a/src/test/bench/std-smallintmap.rs +++ b/src/test/bench/std-smallintmap.rs @@ -10,7 +10,7 @@ // Microbenchmark for the smallintmap library -#![feature(collections, std_misc)] +#![feature(collections, duration, duration_span)] use std::collections::VecMap; use std::env; @@ -40,8 +40,8 @@ fn main() { let max = args[1].parse::().unwrap(); let rep = args[2].parse::().unwrap(); - let mut checkf = Duration::seconds(0); - let mut appendf = Duration::seconds(0); + let mut checkf = Duration::new(0, 0); + let mut appendf = Duration::new(0, 0); for _ in 0..rep { let mut map = VecMap::new(); @@ -55,7 +55,7 @@ fn main() { let maxf = max as f64; println!("insert(): {} seconds\n", checkf); - println!(" : {} op/ms\n", maxf / checkf.num_milliseconds() as f64); + println!(" : {} op/s\n", maxf / checkf.secs() as f64); println!("get() : {} seconds\n", appendf); - println!(" : {} op/ms\n", maxf / appendf.num_milliseconds() as f64); + println!(" : {} op/s\n", maxf / appendf.secs() as f64); } diff --git a/src/test/bench/task-perf-alloc-unwind.rs b/src/test/bench/task-perf-alloc-unwind.rs index e091dbfb00e4b..babae4d149f52 100644 --- a/src/test/bench/task-perf-alloc-unwind.rs +++ b/src/test/bench/task-perf-alloc-unwind.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(box_syntax, std_misc, collections)] +#![feature(box_syntax, duration, duration_span, collections)] use std::env; use std::thread; diff --git a/src/test/compile-fail-fulldeps/gated-macro-reexports.rs b/src/test/compile-fail-fulldeps/gated-macro-reexports.rs index 022a6b4f2f7de..b3dbcb743a135 100644 --- a/src/test/compile-fail-fulldeps/gated-macro-reexports.rs +++ b/src/test/compile-fail-fulldeps/gated-macro-reexports.rs @@ -11,7 +11,6 @@ // Test that macro reexports item are gated by `macro_reexport` feature gate. // aux-build:macro_reexport_1.rs -// ignore-stage1 #![crate_type = "dylib"] diff --git a/src/test/compile-fail-fulldeps/gated-plugin.rs b/src/test/compile-fail-fulldeps/gated-plugin.rs index 9fa93063ea3a5..4e80ca46c0a84 100644 --- a/src/test/compile-fail-fulldeps/gated-plugin.rs +++ b/src/test/compile-fail-fulldeps/gated-plugin.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:macro_crate_test.rs -// ignore-stage1 #![plugin(macro_crate_test)] //~^ ERROR compiler plugins are experimental and possibly buggy diff --git a/src/test/compile-fail-fulldeps/macro-crate-doesnt-resolve.rs b/src/test/compile-fail-fulldeps/macro-crate-doesnt-resolve.rs index 361840a1618e7..8ac03606720e4 100644 --- a/src/test/compile-fail-fulldeps/macro-crate-doesnt-resolve.rs +++ b/src/test/compile-fail-fulldeps/macro-crate-doesnt-resolve.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:macro_crate_test.rs -// ignore-stage1 #[macro_use] #[no_link] extern crate macro_crate_test; diff --git a/src/test/compile-fail-fulldeps/macro-crate-rlib.rs b/src/test/compile-fail-fulldeps/macro-crate-rlib.rs index 396b1c1de3aa0..5b34d8e3adb08 100644 --- a/src/test/compile-fail-fulldeps/macro-crate-rlib.rs +++ b/src/test/compile-fail-fulldeps/macro-crate-rlib.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:rlib_crate_test.rs -// ignore-stage1 // ignore-tidy-linelength // ignore-cross-compile gives a different error message diff --git a/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs b/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs index ba8e20069c196..b0cd422053260 100644 --- a/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs +++ b/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:macro_crate_test.rs -// ignore-stage1 #[macro_use] #[no_link] extern crate macro_crate_test; diff --git a/src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs b/src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs index c5169b61a2bf9..edbb77fe39063 100644 --- a/src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs +++ b/src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:macro_crate_test.rs -// ignore-stage1 // ignore-cross-compile // // macro_crate_test will not compile on a cross-compiled target because diff --git a/src/test/compile-fail/associated-const-ambiguity-report.rs b/src/test/compile-fail/associated-const-ambiguity-report.rs new file mode 100644 index 0000000000000..22292a6da9dff --- /dev/null +++ b/src/test/compile-fail/associated-const-ambiguity-report.rs @@ -0,0 +1,33 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(associated_consts)] + +trait Foo { + const ID: i32; +} + +trait Bar { + const ID: i32; +} + +impl Foo for i32 { + const ID: i32 = 1; +} + +impl Bar for i32 { + const ID: i32 = 3; +} + +const X: i32 = ::ID; //~ ERROR E0034 + +fn main() { + assert_eq!(1, X); +} diff --git a/src/test/compile-fail/auto-ref-slice-plus-ref.rs b/src/test/compile-fail/auto-ref-slice-plus-ref.rs index ad3f467a45471..f0f0bdfb38ee3 100644 --- a/src/test/compile-fail/auto-ref-slice-plus-ref.rs +++ b/src/test/compile-fail/auto-ref-slice-plus-ref.rs @@ -15,11 +15,11 @@ fn main() { // vectors to slices then automatically create a self reference. let mut a = vec!(0); - a.test_mut(); //~ ERROR does not implement any method in scope named `test_mut` - a.test(); //~ ERROR does not implement any method in scope named `test` + a.test_mut(); //~ ERROR no method named `test_mut` found + a.test(); //~ ERROR no method named `test` found - ([1]).test(); //~ ERROR does not implement any method in scope named `test` - (&[1]).test(); //~ ERROR does not implement any method in scope named `test` + ([1]).test(); //~ ERROR no method named `test` found + (&[1]).test(); //~ ERROR no method named `test` found } trait MyIter { diff --git a/src/test/compile-fail/class-cast-to-trait.rs b/src/test/compile-fail/class-cast-to-trait.rs index 31e09e877c708..af83b0ecbf22c 100644 --- a/src/test/compile-fail/class-cast-to-trait.rs +++ b/src/test/compile-fail/class-cast-to-trait.rs @@ -60,5 +60,5 @@ fn cat(in_x : usize, in_y : isize, in_name: String) -> cat { fn main() { let nyan: Box = box cat(0, 2, "nyan".to_string()) as Box; - nyan.eat(); //~ ERROR does not implement any method in scope named `eat` + nyan.eat(); //~ ERROR no method named `eat` found } diff --git a/src/test/compile-fail/coherence_inherent.rs b/src/test/compile-fail/coherence_inherent.rs index 2c3fbc827aad6..087b8c14e3575 100644 --- a/src/test/compile-fail/coherence_inherent.rs +++ b/src/test/compile-fail/coherence_inherent.rs @@ -38,7 +38,7 @@ mod NoImport { use Lib::TheStruct; fn call_the_fn(s: &TheStruct) { - s.the_fn(); //~ ERROR does not implement any method in scope named `the_fn` + s.the_fn(); //~ ERROR no method named `the_fn` found } } diff --git a/src/test/compile-fail/coherence_inherent_cc.rs b/src/test/compile-fail/coherence_inherent_cc.rs index 4eb9864bc9c59..442c4c89de4e1 100644 --- a/src/test/compile-fail/coherence_inherent_cc.rs +++ b/src/test/compile-fail/coherence_inherent_cc.rs @@ -30,7 +30,7 @@ mod NoImport { use coherence_inherent_cc_lib::TheStruct; fn call_the_fn(s: &TheStruct) { - s.the_fn(); //~ ERROR does not implement any method in scope named `the_fn` + s.the_fn(); //~ ERROR no method named `the_fn` found } } diff --git a/src/test/compile-fail/copy-a-resource.rs b/src/test/compile-fail/copy-a-resource.rs index 98402591e728a..70633c92e6433 100644 --- a/src/test/compile-fail/copy-a-resource.rs +++ b/src/test/compile-fail/copy-a-resource.rs @@ -26,6 +26,6 @@ fn foo(i:isize) -> foo { fn main() { let x = foo(10); let _y = x.clone(); - //~^ ERROR does not implement any method in scope + //~^ ERROR no method named `clone` found println!("{:?}", x); } diff --git a/src/test/compile-fail/empty-macro-use.rs b/src/test/compile-fail/empty-macro-use.rs index fbf6287db9444..d8cf23d1ff0bb 100644 --- a/src/test/compile-fail/empty-macro-use.rs +++ b/src/test/compile-fail/empty-macro-use.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:two_macros.rs -// ignore-stage1 #[macro_use()] extern crate two_macros; diff --git a/src/test/compile-fail/issue-10465.rs b/src/test/compile-fail/issue-10465.rs index a5e374a7a8b19..ed91e935407b9 100644 --- a/src/test/compile-fail/issue-10465.rs +++ b/src/test/compile-fail/issue-10465.rs @@ -24,7 +24,7 @@ pub mod b { use b::B; fn foo(b: &B) { - b.foo(); //~ ERROR: does not implement any method in scope named + b.foo(); //~ ERROR: no method named `foo` found } } diff --git a/src/test/compile-fail/issue-13853.rs b/src/test/compile-fail/issue-13853.rs index 251da2c6b3ee9..f5d158d64e19f 100644 --- a/src/test/compile-fail/issue-13853.rs +++ b/src/test/compile-fail/issue-13853.rs @@ -31,7 +31,7 @@ impl Node for Stuff { } fn iterate>(graph: &G) { - for node in graph.iter() { //~ ERROR does not implement any method in scope named + for node in graph.iter() { //~ ERROR no method named `iter` found node.zomg(); //~ error: the type of this value must be known in this context } } diff --git a/src/test/compile-fail/issue-14084.rs b/src/test/compile-fail/issue-14084.rs index 92e0dd3ad0e52..003c6644f7f02 100644 --- a/src/test/compile-fail/issue-14084.rs +++ b/src/test/compile-fail/issue-14084.rs @@ -12,5 +12,5 @@ fn main() { box ( () ) 0; - //~^ ERROR: only the managed heap and exchange heap are currently supported + //~^ ERROR: only the exchange heap is currently supported } diff --git a/src/test/compile-fail/issue-18343.rs b/src/test/compile-fail/issue-18343.rs index f87a0d774fa7c..43e9ca5fa6e7a 100644 --- a/src/test/compile-fail/issue-18343.rs +++ b/src/test/compile-fail/issue-18343.rs @@ -14,6 +14,6 @@ struct Obj where F: FnMut() -> u32 { fn main() { let o = Obj { closure: || 42 }; - o.closure(); //~ ERROR does not implement any method in scope named `closure` + o.closure(); //~ ERROR no method named `closure` found //~^ NOTE use `(s.closure)(...)` if you meant to call the function stored in the `closure` field } diff --git a/src/test/compile-fail/issue-1871.rs b/src/test/compile-fail/issue-1871.rs index 423d87861cb68..e4d132c86415a 100644 --- a/src/test/compile-fail/issue-1871.rs +++ b/src/test/compile-fail/issue-1871.rs @@ -14,7 +14,7 @@ fn main() { let f = 42; let _g = if f < 5 { - f.honk() //~ ERROR does not implement any method in scope named `honk` + f.honk() //~ ERROR no method named `honk` found } else { () diff --git a/src/test/compile-fail/issue-19521.rs b/src/test/compile-fail/issue-19521.rs index 61cff598b2aee..58a95e9da2bf3 100644 --- a/src/test/compile-fail/issue-19521.rs +++ b/src/test/compile-fail/issue-19521.rs @@ -11,5 +11,5 @@ #![feature(unboxed_closures)] fn main() { - "".homura()(); //~ ERROR does not implement any method + "".homura()(); //~ ERROR no method named `homura` found } diff --git a/src/test/compile-fail/issue-19692.rs b/src/test/compile-fail/issue-19692.rs index 7b84ba0343a33..88ae0f835d0d7 100644 --- a/src/test/compile-fail/issue-19692.rs +++ b/src/test/compile-fail/issue-19692.rs @@ -11,7 +11,7 @@ struct Homura; fn akemi(homura: Homura) { - let Some(ref madoka) = Some(homura.kaname()); //~ ERROR does not implement any method + let Some(ref madoka) = Some(homura.kaname()); //~ ERROR no method named `kaname` found madoka.clone(); //~ ERROR the type of this value must be known in this context } diff --git a/src/test/compile-fail/issue-2149.rs b/src/test/compile-fail/issue-2149.rs index ea305c96af4a1..bb170ef7d0036 100644 --- a/src/test/compile-fail/issue-2149.rs +++ b/src/test/compile-fail/issue-2149.rs @@ -22,5 +22,5 @@ impl vec_monad for Vec { } fn main() { ["hi"].bind(|x| [x] ); - //~^ ERROR type `[&str; 1]` does not implement any method in scope named `bind` + //~^ ERROR no method named `bind` found for type `[&str; 1]` in the current scope } diff --git a/src/test/compile-fail/issue-24968.rs b/src/test/compile-fail/issue-24968.rs new file mode 100644 index 0000000000000..f51b77b0ee539 --- /dev/null +++ b/src/test/compile-fail/issue-24968.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn foo(_: Self) { + //~^ ERROR use of `Self` outside of an impl or trait +} + +fn main() {} diff --git a/src/test/compile-fail/issue-2823.rs b/src/test/compile-fail/issue-2823.rs index 1996cb737fc72..631bcb7bd9eb9 100644 --- a/src/test/compile-fail/issue-2823.rs +++ b/src/test/compile-fail/issue-2823.rs @@ -20,5 +20,5 @@ impl Drop for C { fn main() { let c = C{ x: 2}; - let _d = c.clone(); //~ ERROR does not implement any method in scope + let _d = c.clone(); //~ ERROR no method named `clone` found } diff --git a/src/test/compile-fail/issue-3563.rs b/src/test/compile-fail/issue-3563.rs index 0e1cc18dba910..29c1c584eed24 100644 --- a/src/test/compile-fail/issue-3563.rs +++ b/src/test/compile-fail/issue-3563.rs @@ -11,7 +11,7 @@ trait A { fn a(&self) { || self.b() - //~^ ERROR type `&Self` does not implement any method in scope named `b` + //~^ ERROR no method named `b` found for type `&Self` in the current scope //~| ERROR mismatched types //~| expected `()` //~| found closure diff --git a/src/test/compile-fail/issue-3702-2.rs b/src/test/compile-fail/issue-3702-2.rs index 026ee89c0b2b5..325f05841f408 100644 --- a/src/test/compile-fail/issue-3702-2.rs +++ b/src/test/compile-fail/issue-3702-2.rs @@ -23,7 +23,7 @@ trait Add { impl Add for isize { fn to_int(&self) -> isize { *self } fn add_dynamic(&self, other: &Add) -> isize { - self.to_int() + other.to_int() //~ ERROR multiple applicable methods in scope + self.to_int() + other.to_int() //~ ERROR multiple applicable items in scope } } diff --git a/src/test/compile-fail/issue-3707.rs b/src/test/compile-fail/issue-3707.rs index 0d57a8a50cc6a..ad56b125b087f 100644 --- a/src/test/compile-fail/issue-3707.rs +++ b/src/test/compile-fail/issue-3707.rs @@ -17,7 +17,7 @@ impl Obj { return 1+1 == 2 } pub fn chirp(&self) { - self.boom(); //~ ERROR `&Obj` does not implement any method in scope named `boom` + self.boom(); //~ ERROR no method named `boom` found for type `&Obj` in the current scope } } diff --git a/src/test/compile-fail/issue-5153.rs b/src/test/compile-fail/issue-5153.rs index c10c7cba45559..da32408e19924 100644 --- a/src/test/compile-fail/issue-5153.rs +++ b/src/test/compile-fail/issue-5153.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: type `&Foo` does not implement any method in scope named `foo` - trait Foo { fn foo(self: Box); } @@ -20,4 +18,5 @@ impl Foo for isize { fn main() { (&5 as &Foo).foo(); + //~^ ERROR: no method named `foo` found for type `&Foo` in the current scope } diff --git a/src/test/compile-fail/issue-7575.rs b/src/test/compile-fail/issue-7575.rs index 6b320f400a809..6c7196527efdb 100644 --- a/src/test/compile-fail/issue-7575.rs +++ b/src/test/compile-fail/issue-7575.rs @@ -71,15 +71,15 @@ impl ManyImplTrait for Myisize {} fn no_param_bound(u: usize, m: Myisize) -> usize { u.f8(42) + u.f9(342) + m.fff(42) - //~^ ERROR type `usize` does not implement any method in scope named `f9` + //~^ ERROR no method named `f9` found for type `usize` in the current scope //~^^ NOTE found defined static methods, maybe a `self` is missing? - //~^^^ ERROR type `Myisize` does not implement any method in scope named `fff` + //~^^^ ERROR no method named `fff` found for type `Myisize` in the current scope //~^^^^ NOTE found defined static methods, maybe a `self` is missing? } fn param_bound(t: T) -> bool { t.is_str() - //~^ ERROR type `T` does not implement any method in scope named `is_str` + //~^ ERROR no method named `is_str` found for type `T` in the current scope //~^^ NOTE found defined static methods, maybe a `self` is missing? } diff --git a/src/test/compile-fail/issue-7950.rs b/src/test/compile-fail/issue-7950.rs index 01b90f5680f2c..003329a2d7de2 100644 --- a/src/test/compile-fail/issue-7950.rs +++ b/src/test/compile-fail/issue-7950.rs @@ -13,5 +13,5 @@ struct Foo; fn main() { - Foo::bar(); //~ ERROR type `Foo` does not implement any method in scope named `bar` + Foo::bar(); //~ ERROR no associated item named `bar` found for type `Foo` in the current scope } diff --git a/src/test/compile-fail/macro-backtrace-invalid-internals.rs b/src/test/compile-fail/macro-backtrace-invalid-internals.rs index df906d723566c..34aa1c75872f3 100644 --- a/src/test/compile-fail/macro-backtrace-invalid-internals.rs +++ b/src/test/compile-fail/macro-backtrace-invalid-internals.rs @@ -12,7 +12,7 @@ macro_rules! fake_method_stmt { //~ NOTE in expansion of () => { - 1.fake() //~ ERROR does not implement any method + 1.fake() //~ ERROR no method named `fake` found } } @@ -30,7 +30,7 @@ macro_rules! fake_anon_field_stmt { //~ NOTE in expansion of macro_rules! fake_method_expr { //~ NOTE in expansion of () => { - 1.fake() //~ ERROR does not implement any method + 1.fake() //~ ERROR no method named `fake` found } } diff --git a/src/test/compile-fail/macro-crate-nonterminal-non-root.rs b/src/test/compile-fail/macro-crate-nonterminal-non-root.rs index 67aaf05c3101b..76211b88bd7c3 100644 --- a/src/test/compile-fail/macro-crate-nonterminal-non-root.rs +++ b/src/test/compile-fail/macro-crate-nonterminal-non-root.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:macro_crate_nonterminal.rs -// ignore-stage1 mod foo { #[macro_use] diff --git a/src/test/compile-fail/macro-no-implicit-reexport.rs b/src/test/compile-fail/macro-no-implicit-reexport.rs index e8d9f444cefc6..cd6640f8b6dda 100644 --- a/src/test/compile-fail/macro-no-implicit-reexport.rs +++ b/src/test/compile-fail/macro-no-implicit-reexport.rs @@ -10,7 +10,6 @@ // aux-build:macro_reexport_1.rs // aux-build:macro_non_reexport_2.rs -// ignore-stage1 #[macro_use] #[no_link] extern crate macro_non_reexport_2; diff --git a/src/test/compile-fail/macro-reexport-not-locally-visible.rs b/src/test/compile-fail/macro-reexport-not-locally-visible.rs index 26de51a7cf8c3..ca334d9fd2d78 100644 --- a/src/test/compile-fail/macro-reexport-not-locally-visible.rs +++ b/src/test/compile-fail/macro-reexport-not-locally-visible.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:macro_reexport_1.rs -// ignore-stage1 #![feature(macro_reexport)] diff --git a/src/test/compile-fail/macro-reexport-undef.rs b/src/test/compile-fail/macro-reexport-undef.rs index e9b3ceff83de4..8fa6b32905ceb 100644 --- a/src/test/compile-fail/macro-reexport-undef.rs +++ b/src/test/compile-fail/macro-reexport-undef.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:two_macros.rs -// ignore-stage1 #[macro_use(macro_two)] #[macro_reexport(no_way)] //~ ERROR reexported macro not found diff --git a/src/test/compile-fail/macro-use-undef.rs b/src/test/compile-fail/macro-use-undef.rs index a5a350bd30e1a..dd725aae95e89 100644 --- a/src/test/compile-fail/macro-use-undef.rs +++ b/src/test/compile-fail/macro-use-undef.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:two_macros.rs -// ignore-stage1 #[macro_use(macro_two, no_way)] //~ ERROR imported macro not found extern crate two_macros; diff --git a/src/test/compile-fail/macro-use-wrong-name.rs b/src/test/compile-fail/macro-use-wrong-name.rs index 4e0486f0db7e9..4dc65434dc7e1 100644 --- a/src/test/compile-fail/macro-use-wrong-name.rs +++ b/src/test/compile-fail/macro-use-wrong-name.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:two_macros.rs -// ignore-stage1 #[macro_use(macro_one)] extern crate two_macros; diff --git a/src/test/compile-fail/method-call-err-msg.rs b/src/test/compile-fail/method-call-err-msg.rs index 2f82441762f75..3434cf96fce94 100644 --- a/src/test/compile-fail/method-call-err-msg.rs +++ b/src/test/compile-fail/method-call-err-msg.rs @@ -25,6 +25,6 @@ fn main() { let y = Foo; y.zero() - .take() //~ ERROR type `Foo` does not implement any method in scope named `take` + .take() //~ ERROR no method named `take` found for type `Foo` in the current scope .one(0); } diff --git a/src/test/compile-fail/method-suggestion-no-duplication.rs b/src/test/compile-fail/method-suggestion-no-duplication.rs index 1d0c4254eda2e..e6f3c8ab3170e 100644 --- a/src/test/compile-fail/method-suggestion-no-duplication.rs +++ b/src/test/compile-fail/method-suggestion-no-duplication.rs @@ -16,7 +16,7 @@ fn foo(f: F) where F: FnMut(Foo) {} fn main() { foo(|s| s.is_empty()); - //~^ ERROR does not implement any method + //~^ ERROR no method named `is_empty` found //~^^ HELP #1: `core::slice::SliceExt` //~^^^ HELP #2: `core::str::StrExt` } diff --git a/src/test/compile-fail/missing-macro-use.rs b/src/test/compile-fail/missing-macro-use.rs index 0153d71fb268f..bbce9c2128757 100644 --- a/src/test/compile-fail/missing-macro-use.rs +++ b/src/test/compile-fail/missing-macro-use.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:two_macros.rs -// ignore-stage1 extern crate two_macros; diff --git a/src/test/compile-fail/no-method-suggested-traits.rs b/src/test/compile-fail/no-method-suggested-traits.rs index 21f8a982806a9..08c848a09ab09 100644 --- a/src/test/compile-fail/no-method-suggested-traits.rs +++ b/src/test/compile-fail/no-method-suggested-traits.rs @@ -33,36 +33,36 @@ fn main() { 1u32.method(); //~^ HELP following traits are implemented but not in scope, perhaps add a `use` for one of them - //~^^ ERROR does not implement + //~^^ ERROR no method named //~^^^ HELP `foo::Bar` //~^^^^ HELP `no_method_suggested_traits::foo::PubPub` std::rc::Rc::new(&mut Box::new(&1u32)).method(); //~^ HELP following traits are implemented but not in scope, perhaps add a `use` for one of them - //~^^ ERROR does not implement + //~^^ ERROR no method named //~^^^ HELP `foo::Bar` //~^^^^ HELP `no_method_suggested_traits::foo::PubPub` 'a'.method(); - //~^ ERROR does not implement + //~^ ERROR no method named //~^^ HELP the following trait is implemented but not in scope, perhaps add a `use` for it: //~^^^ HELP `foo::Bar` std::rc::Rc::new(&mut Box::new(&'a')).method(); - //~^ ERROR does not implement + //~^ ERROR no method named //~^^ HELP the following trait is implemented but not in scope, perhaps add a `use` for it: //~^^^ HELP `foo::Bar` 1i32.method(); - //~^ ERROR does not implement + //~^ ERROR no method named //~^^ HELP the following trait is implemented but not in scope, perhaps add a `use` for it: //~^^^ HELP `no_method_suggested_traits::foo::PubPub` std::rc::Rc::new(&mut Box::new(&1i32)).method(); - //~^ ERROR does not implement + //~^ ERROR no method named //~^^ HELP the following trait is implemented but not in scope, perhaps add a `use` for it: //~^^^ HELP `no_method_suggested_traits::foo::PubPub` Foo.method(); - //~^ ERROR does not implement - //~^^ HELP following traits define a method `method`, perhaps you need to implement one of them + //~^ ERROR no method named + //~^^ HELP following traits define an item `method`, perhaps you need to implement one of them //~^^^ HELP `foo::Bar` //~^^^^ HELP `no_method_suggested_traits::foo::PubPub` //~^^^^^ HELP `no_method_suggested_traits::reexport::Reexported` @@ -70,8 +70,8 @@ fn main() { //~^^^^^^^ HELP `no_method_suggested_traits::qux::PrivPub` //~^^^^^^^^ HELP `no_method_suggested_traits::quz::PrivPriv` std::rc::Rc::new(&mut Box::new(&Foo)).method(); - //~^ ERROR does not implement - //~^^ HELP following traits define a method `method`, perhaps you need to implement one of them + //~^ ERROR no method named + //~^^ HELP following traits define an item `method`, perhaps you need to implement one of them //~^^^ HELP `foo::Bar` //~^^^^ HELP `no_method_suggested_traits::foo::PubPub` //~^^^^^ HELP `no_method_suggested_traits::reexport::Reexported` @@ -80,55 +80,55 @@ fn main() { //~^^^^^^^^ HELP `no_method_suggested_traits::quz::PrivPriv` 1u64.method2(); - //~^ ERROR does not implement - //~^^ HELP the following trait defines a method `method2`, perhaps you need to implement it + //~^ ERROR no method named + //~^^ HELP the following trait defines an item `method2`, perhaps you need to implement it //~^^^ HELP `foo::Bar` std::rc::Rc::new(&mut Box::new(&1u64)).method2(); - //~^ ERROR does not implement - //~^^ HELP the following trait defines a method `method2`, perhaps you need to implement it + //~^ ERROR no method named + //~^^ HELP the following trait defines an item `method2`, perhaps you need to implement it //~^^^ HELP `foo::Bar` no_method_suggested_traits::Foo.method2(); - //~^ ERROR does not implement - //~^^ HELP following trait defines a method `method2`, perhaps you need to implement it + //~^ ERROR no method named + //~^^ HELP following trait defines an item `method2`, perhaps you need to implement it //~^^^ HELP `foo::Bar` std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2(); - //~^ ERROR does not implement - //~^^ HELP following trait defines a method `method2`, perhaps you need to implement it + //~^ ERROR no method named + //~^^ HELP following trait defines an item `method2`, perhaps you need to implement it //~^^^ HELP `foo::Bar` no_method_suggested_traits::Bar::X.method2(); - //~^ ERROR does not implement - //~^^ HELP following trait defines a method `method2`, perhaps you need to implement it + //~^ ERROR no method named + //~^^ HELP following trait defines an item `method2`, perhaps you need to implement it //~^^^ HELP `foo::Bar` std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2(); - //~^ ERROR does not implement - //~^^ HELP following trait defines a method `method2`, perhaps you need to implement it + //~^ ERROR no method named + //~^^ HELP following trait defines an item `method2`, perhaps you need to implement it //~^^^ HELP `foo::Bar` Foo.method3(); - //~^ ERROR does not implement - //~^^ HELP following trait defines a method `method3`, perhaps you need to implement it + //~^ ERROR no method named + //~^^ HELP following trait defines an item `method3`, perhaps you need to implement it //~^^^ HELP `no_method_suggested_traits::foo::PubPub` std::rc::Rc::new(&mut Box::new(&Foo)).method3(); - //~^ ERROR does not implement - //~^^ HELP following trait defines a method `method3`, perhaps you need to implement it + //~^ ERROR no method named + //~^^ HELP following trait defines an item `method3`, perhaps you need to implement it //~^^^ HELP `no_method_suggested_traits::foo::PubPub` Bar::X.method3(); - //~^ ERROR does not implement - //~^^ HELP following trait defines a method `method3`, perhaps you need to implement it + //~^ ERROR no method named + //~^^ HELP following trait defines an item `method3`, perhaps you need to implement it //~^^^ HELP `no_method_suggested_traits::foo::PubPub` std::rc::Rc::new(&mut Box::new(&Bar::X)).method3(); - //~^ ERROR does not implement - //~^^ HELP following trait defines a method `method3`, perhaps you need to implement it + //~^ ERROR no method named + //~^^ HELP following trait defines an item `method3`, perhaps you need to implement it //~^^^ HELP `no_method_suggested_traits::foo::PubPub` // should have no help: - 1_usize.method3(); //~ ERROR does not implement - std::rc::Rc::new(&mut Box::new(&1_usize)).method3(); //~ ERROR does not implement - no_method_suggested_traits::Foo.method3(); //~ ERROR does not implement + 1_usize.method3(); //~ ERROR no method named + std::rc::Rc::new(&mut Box::new(&1_usize)).method3(); //~ ERROR no method named + no_method_suggested_traits::Foo.method3(); //~ ERROR no method named std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method3(); - //~^ ERROR does not implement - no_method_suggested_traits::Bar::X.method3(); //~ ERROR does not implement + //~^ ERROR no method named + no_method_suggested_traits::Bar::X.method3(); //~ ERROR no method named std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3(); - //~^ ERROR does not implement + //~^ ERROR no method named } diff --git a/src/test/compile-fail/non-copyable-void.rs b/src/test/compile-fail/non-copyable-void.rs index 40b641519b06d..fd245f38a0c92 100644 --- a/src/test/compile-fail/non-copyable-void.rs +++ b/src/test/compile-fail/non-copyable-void.rs @@ -15,6 +15,6 @@ fn main() { let y : *const libc::c_void = x as *const libc::c_void; unsafe { let _z = (*y).clone(); - //~^ ERROR does not implement any method in scope + //~^ ERROR no method named `clone` found } } diff --git a/src/test/compile-fail/noncopyable-class.rs b/src/test/compile-fail/noncopyable-class.rs index df135c3a8e309..f5712b0c957ba 100644 --- a/src/test/compile-fail/noncopyable-class.rs +++ b/src/test/compile-fail/noncopyable-class.rs @@ -41,6 +41,6 @@ fn foo(i:isize) -> foo { fn main() { let x = foo(10); - let _y = x.clone(); //~ ERROR does not implement any method in scope + let _y = x.clone(); //~ ERROR no method named `clone` found println!("{:?}", x); } diff --git a/src/test/compile-fail/object-pointer-types.rs b/src/test/compile-fail/object-pointer-types.rs index 84e7f98a40dc2..98c14cee942ed 100644 --- a/src/test/compile-fail/object-pointer-types.rs +++ b/src/test/compile-fail/object-pointer-types.rs @@ -19,19 +19,19 @@ trait Foo { fn borrowed_receiver(x: &Foo) { x.borrowed(); x.borrowed_mut(); // See [1] - x.owned(); //~ ERROR does not implement any method + x.owned(); //~ ERROR no method named `owned` found } fn borrowed_mut_receiver(x: &mut Foo) { x.borrowed(); x.borrowed_mut(); - x.owned(); //~ ERROR does not implement any method + x.owned(); //~ ERROR no method named `owned` found } fn owned_receiver(x: Box) { x.borrowed(); x.borrowed_mut(); // See [1] - x.managed(); //~ ERROR does not implement any method + x.managed(); //~ ERROR no method named `managed` found x.owned(); } diff --git a/src/test/compile-fail/ret-non-nil.rs b/src/test/compile-fail/ret-non-nil.rs index 4ee3cf4abac4e..6be98fbd82773 100644 --- a/src/test/compile-fail/ret-non-nil.rs +++ b/src/test/compile-fail/ret-non-nil.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: `return;` in function returning non-nil +// error-pattern: `return;` in a function whose return type is not `()` fn f() { return; } diff --git a/src/test/compile-fail/trait-impl-1.rs b/src/test/compile-fail/trait-impl-1.rs index dadcbd5bce710..e682d3c81e793 100644 --- a/src/test/compile-fail/trait-impl-1.rs +++ b/src/test/compile-fail/trait-impl-1.rs @@ -22,5 +22,5 @@ impl T for i32 {} fn main() { let x = &42i32; - x.foo(); //~ERROR: type `&i32` does not implement any method in scope named `foo` + x.foo(); //~ERROR: no method named `foo` found for type `&i32` in the current scope } diff --git a/src/test/compile-fail/unboxed-closures-static-call-wrong-trait.rs b/src/test/compile-fail/unboxed-closures-static-call-wrong-trait.rs index 1a52e22419eb4..1c133fbfcdbbf 100644 --- a/src/test/compile-fail/unboxed-closures-static-call-wrong-trait.rs +++ b/src/test/compile-fail/unboxed-closures-static-call-wrong-trait.rs @@ -14,5 +14,5 @@ fn to_fn_mut>(f: F) -> F { f } fn main() { let mut_ = to_fn_mut(|x| x); - mut_.call((0, )); //~ ERROR does not implement any method in scope named `call` + mut_.call((0, )); //~ ERROR no method named `call` found } diff --git a/src/test/compile-fail/unique-object-noncopyable.rs b/src/test/compile-fail/unique-object-noncopyable.rs index 5074d00ca1587..c44718c4fc9c2 100644 --- a/src/test/compile-fail/unique-object-noncopyable.rs +++ b/src/test/compile-fail/unique-object-noncopyable.rs @@ -31,5 +31,5 @@ impl Foo for Bar { fn main() { let x = box Bar { x: 10 }; let y: Box = x as Box; - let _z = y.clone(); //~ ERROR does not implement any method in scope + let _z = y.clone(); //~ ERROR no method named `clone` found } diff --git a/src/test/compile-fail/unique-pinned-nocopy.rs b/src/test/compile-fail/unique-pinned-nocopy.rs index 2ec10d08bb41d..d971940db38f5 100644 --- a/src/test/compile-fail/unique-pinned-nocopy.rs +++ b/src/test/compile-fail/unique-pinned-nocopy.rs @@ -20,6 +20,6 @@ impl Drop for r { fn main() { // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. let i = Box::new(r { b: true }); - let _j = i.clone(); //~ ERROR not implement + let _j = i.clone(); //~ ERROR no method named `clone` found println!("{:?}", i); } diff --git a/src/test/run-pass-fulldeps/issue-13560.rs b/src/test/run-pass-fulldeps/issue-13560.rs index fc9f241af7f10..88be7fe1212d1 100644 --- a/src/test/run-pass-fulldeps/issue-13560.rs +++ b/src/test/run-pass-fulldeps/issue-13560.rs @@ -11,7 +11,6 @@ // aux-build:issue-13560-1.rs // aux-build:issue-13560-2.rs // aux-build:issue-13560-3.rs -// ignore-stage1 // ignore-musl // Regression test for issue #13560, the test itself is all in the dependent diff --git a/src/test/run-pass/associated-const-match-patterns.rs b/src/test/run-pass/associated-const-match-patterns.rs index eeaacbf9dcc78..62e90d7a6e22b 100644 --- a/src/test/run-pass/associated-const-match-patterns.rs +++ b/src/test/run-pass/associated-const-match-patterns.rs @@ -41,6 +41,10 @@ fn main() { _ => false, }); // Trait impl + assert!(match Bar::Var1 { + Foo::THEBAR => true, + _ => false, + }); assert!(match Bar::Var1 { ::THEBAR => true, _ => false, diff --git a/src/test/run-pass/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs index df7cedd1c2938..83ce0db365f8b 100644 --- a/src/test/run-pass/core-run-destroy.rs +++ b/src/test/run-pass/core-run-destroy.rs @@ -16,7 +16,7 @@ // instead of in std. #![reexport_test_harness_main = "test_main"] -#![feature(libc, std_misc)] +#![feature(libc, std_misc, duration)] extern crate libc; diff --git a/src/test/run-pass/crate-attributes-using-cfg_attr.rs b/src/test/run-pass/crate-attributes-using-cfg_attr.rs new file mode 100644 index 0000000000000..72ccc6723f921 --- /dev/null +++ b/src/test/run-pass/crate-attributes-using-cfg_attr.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:crate-attributes-using-cfg_attr.rs + +extern crate crate_attributes_using_cfg_attr; + +pub fn main() {} diff --git a/src/test/run-pass/macro-crate-nonterminal-renamed.rs b/src/test/run-pass/macro-crate-nonterminal-renamed.rs index ed7b1cbacadd7..93f5899e3ac90 100644 --- a/src/test/run-pass/macro-crate-nonterminal-renamed.rs +++ b/src/test/run-pass/macro-crate-nonterminal-renamed.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:macro_crate_nonterminal.rs -// ignore-stage1 #[macro_use] extern crate macro_crate_nonterminal as new_name; diff --git a/src/test/run-pass/macro-crate-nonterminal.rs b/src/test/run-pass/macro-crate-nonterminal.rs index 9882f806a9eea..28f9393ab7a10 100644 --- a/src/test/run-pass/macro-crate-nonterminal.rs +++ b/src/test/run-pass/macro-crate-nonterminal.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:macro_crate_nonterminal.rs -// ignore-stage1 #[macro_use] extern crate macro_crate_nonterminal; diff --git a/src/test/run-pass/macro-export-inner-module.rs b/src/test/run-pass/macro-export-inner-module.rs index 1c7b2530b903b..e39f81e49d7c4 100644 --- a/src/test/run-pass/macro-export-inner-module.rs +++ b/src/test/run-pass/macro-export-inner-module.rs @@ -9,7 +9,6 @@ // except according to those terms. //aux-build:macro_export_inner_module.rs -//ignore-stage1 #[macro_use] #[no_link] extern crate macro_export_inner_module; diff --git a/src/test/run-pass/macro-reexport-no-intermediate-use.rs b/src/test/run-pass/macro-reexport-no-intermediate-use.rs index dba623876b0a9..de7df1ec02125 100644 --- a/src/test/run-pass/macro-reexport-no-intermediate-use.rs +++ b/src/test/run-pass/macro-reexport-no-intermediate-use.rs @@ -10,7 +10,6 @@ // aux-build:macro_reexport_1.rs // aux-build:macro_reexport_2_no_use.rs -// ignore-stage1 #[macro_use] #[no_link] extern crate macro_reexport_2_no_use; diff --git a/src/test/run-pass/macro-reexport.rs b/src/test/run-pass/macro-reexport.rs index a6af8c45c2439..b8926eca9e996 100644 --- a/src/test/run-pass/macro-reexport.rs +++ b/src/test/run-pass/macro-reexport.rs @@ -10,7 +10,6 @@ // aux-build:macro_reexport_1.rs // aux-build:macro_reexport_2.rs -// ignore-stage1 #[macro_use] #[no_link] extern crate macro_reexport_2; diff --git a/src/test/run-pass/macro-use-all-and-none.rs b/src/test/run-pass/macro-use-all-and-none.rs index b46910290a8a0..60e1d6287f181 100644 --- a/src/test/run-pass/macro-use-all-and-none.rs +++ b/src/test/run-pass/macro-use-all-and-none.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:two_macros.rs -// ignore-stage1 #[macro_use] #[macro_use()] diff --git a/src/test/run-pass/macro-use-all.rs b/src/test/run-pass/macro-use-all.rs index cf72d2c623044..ca9c0e23e7c33 100644 --- a/src/test/run-pass/macro-use-all.rs +++ b/src/test/run-pass/macro-use-all.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:two_macros.rs -// ignore-stage1 #[macro_use] extern crate two_macros; diff --git a/src/test/run-pass/macro-use-both.rs b/src/test/run-pass/macro-use-both.rs index 4b0814bef04b8..7e0a374ef1521 100644 --- a/src/test/run-pass/macro-use-both.rs +++ b/src/test/run-pass/macro-use-both.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:two_macros.rs -// ignore-stage1 #[macro_use(macro_one, macro_two)] extern crate two_macros; diff --git a/src/test/run-pass/macro-use-one.rs b/src/test/run-pass/macro-use-one.rs index 7911fec94da8b..6a30b3e55ba9a 100644 --- a/src/test/run-pass/macro-use-one.rs +++ b/src/test/run-pass/macro-use-one.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:two_macros.rs -// ignore-stage1 #[macro_use(macro_two)] extern crate two_macros; diff --git a/src/test/run-pass/std-sync-right-kind-impls.rs b/src/test/run-pass/std-sync-right-kind-impls.rs index 058777bb05e5e..36314c5e14ac2 100644 --- a/src/test/run-pass/std-sync-right-kind-impls.rs +++ b/src/test/run-pass/std-sync-right-kind-impls.rs @@ -10,7 +10,7 @@ // pretty-expanded FIXME #23616 -#![feature(std_misc, alloc)] +#![feature(std_misc, alloc, static_condvar)] use std::sync; diff --git a/src/test/run-pass/two-macro-use.rs b/src/test/run-pass/two-macro-use.rs index 51c0b75e8fbe6..5df9d0222b4bb 100644 --- a/src/test/run-pass/two-macro-use.rs +++ b/src/test/run-pass/two-macro-use.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:two_macros.rs -// ignore-stage1 #[macro_use(macro_one)] #[macro_use(macro_two)]