diff --git a/src/doc/index.md b/src/doc/index.md index 3add2774105e0..2e36831d7e86f 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -6,55 +6,72 @@ nav { } -This page is an overview of the documentation included with your Rust install. -Other unofficial documentation may exist elsewhere; for example, the [Rust -Learning] project collects documentation from the community, and [Docs.rs] -builds documentation for individual Rust packages. +Welcome to an overview of the documentation provided by the Rust project. +All of these projects are managed by the Docs Team; there are other +unofficial documentation resources as well! -# API Documentation +Many of these resources take the form of "books"; we collectively call these +"The Rust Bookshelf." Some are large, some are small. -Rust provides a standard library with a number of features; [we host its -documentation here][api]. +## Learn Rust -# Extended Error Documentation +If you'd like to learn Rust, this is the spot for you! All of these resources +assume that you have programmed before, but not in any specific language: + +### The Rust Programming Language + +Affectionately nicknamed "the book," [The Rust Programming +Language](book/index.html) will give you an overview of the language from +first principles. You'll build a few projects along the way, and by the end, +you'll have a solid grasp of the language. + +### Rust By Example + +If reading multiple hundreds of pages about a language isn't your style, then +[Rust By Example](rust-by-example/index.html) has you covered. While the book talks about code with +a lot of words, RBE shows off a bunch of code, and keeps the talking to a +minimum. It also includes exercises! + +## Use Rust + +Once you've gotten familliar with the language, these resources can help you +when you're actually using it day-to-day. + +### The Standard Library + +Rust's standard library has [extensive API documentation](std/index.html), +with explanations of how to use various things, as well as example code for +accomplishing various tasks. + +### The Cargo Book + +[The Cargo Book](cargo/index.html) is a guide to Cargo, Rust's build tool and dependency manager. + +### The Rustdoc Book + +[The Rustdoc Book](rustdoc/index.html) describes our documentation tool, `rustdoc`. + +### Extended Error Listing Many of Rust's errors come with error codes, and you can request extended -diagnostics from the compiler on those errors. We also [have the text of those -extended errors on the web][err], if you prefer to read them that way. - -# The Rust Bookshelf - -Rust provides a number of book-length sets of documentation, collectively -nicknamed 'The Rust Bookshelf.' - -* [The Rust Programming Language][book] teaches you how to program in Rust. -* [Rust By Example][rbe] teaches you how to program in Rust using editable examples. -* [The Cargo Book][cargo-book] is a guide to Cargo, Rust's build tool and dependency manager. -* [The Unstable Book][unstable-book] has documentation for unstable features. -* [The Rustonomicon][nomicon] is your guidebook to the dark arts of unsafe Rust. -* [The Reference][ref] is not a formal spec, but is more detailed and comprehensive than the book. -* [The Rustdoc Book][rustdoc-book] describes our documentation tool, `rustdoc`. - -Initially, documentation lands in the Unstable Book, and then, as part of the -stabilization process, is moved into the Book, Nomicon, or Reference. - -Another few words about the reference: it is guaranteed to be accurate, but not -complete. We have a policy that features must have documentation to be stabilized, -but we did not always have this policy, and so there are some stable things that -are not yet in the reference. We're working on back-filling things that landed -before this policy was put into place. That work is being tracked -[here][refchecklist]. - -[Rust Learning]: https://github.com/ctjhoa/rust-learning -[Docs.rs]: https://docs.rs/ -[api]: std/index.html -[ref]: reference/index.html -[refchecklist]: https://github.com/rust-lang-nursery/reference/issues/9 -[err]: error-index.html -[book]: book/index.html -[rbe]: rust-by-example/index.html -[nomicon]: nomicon/index.html -[unstable-book]: unstable-book/index.html -[rustdoc-book]: rustdoc/index.html -[cargo-book]: cargo/index.html +diagnostics from the compiler on those errors. You can also [read them +here](error-index.html), if you prefer to read them that way. + +## Master Rust + +Once you're quite familiar with the language, you may find these advanced +resources useful. + +### The Reference + +[The Reference](reference/index.html) is not a formal spec, but is more detailed and +comprehensive than the book. + +### The Rustonomicon + +[The Rustonomicon](nomicon/index.html) is your guidebook to the dark arts of unsafe +Rust. It's also sometimes called "the 'nomicon." + +### The Unstable Book +[The Unstable Book](unstable-book/index.html) has documentation for unstable features. diff --git a/src/doc/unstable-book/src/library-features/splice.md b/src/doc/unstable-book/src/library-features/splice.md deleted file mode 100644 index 2e4bb1a5257c9..0000000000000 --- a/src/doc/unstable-book/src/library-features/splice.md +++ /dev/null @@ -1,22 +0,0 @@ -# `splice` - -The tracking issue for this feature is: [#44643] - -[#44643]: https://github.com/rust-lang/rust/issues/44643 - ------------------------- - -The `splice()` method on `String` allows you to replace a range -of values in a string with another range of values. - -A simple example: - -```rust -#![feature(splice)] -let mut s = String::from("α is alpha, β is beta"); -let beta_offset = s.find('β').unwrap_or(s.len()); - -// Replace the range up until the β from the string -s.splice(..beta_offset, "Α is capital alpha; "); -assert_eq!(s, "Α is capital alpha; β is beta"); -``` diff --git a/src/liballoc/borrow.rs b/src/liballoc/borrow.rs index acae0daa86b6b..c6741ddb822d5 100644 --- a/src/liballoc/borrow.rs +++ b/src/liballoc/borrow.rs @@ -59,6 +59,7 @@ pub trait ToOwned { /// let vv: Vec = v.to_owned(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "cloning is often expensive and is not expected to have side effects"] fn to_owned(&self) -> Self::Owned; /// Uses borrowed data to replace owned data, usually by cloning. diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 2fad3b0bad4ac..51a7802540192 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -99,7 +99,6 @@ #![feature(fundamental)] #![feature(generic_param_attrs)] #![cfg_attr(stage0, feature(i128_type))] -#![feature(iter_rfold)] #![feature(lang_items)] #![feature(needs_allocator)] #![feature(nonzero)] diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index aa202e2362892..b95aae02894ed 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -1517,7 +1517,7 @@ impl String { } } - /// Creates a splicing iterator that removes the specified range in the string, + /// Removes the specified range in the string, /// and replaces it with the given string. /// The given string doesn't need to be the same length as the range. /// @@ -1537,21 +1537,20 @@ impl String { /// Basic usage: /// /// ``` - /// #![feature(splice)] /// let mut s = String::from("α is alpha, β is beta"); /// let beta_offset = s.find('β').unwrap_or(s.len()); /// /// // Replace the range up until the β from the string - /// s.splice(..beta_offset, "Α is capital alpha; "); + /// s.replace_range(..beta_offset, "Α is capital alpha; "); /// assert_eq!(s, "Α is capital alpha; β is beta"); /// ``` - #[unstable(feature = "splice", reason = "recently added", issue = "44643")] - pub fn splice(&mut self, range: R, replace_with: &str) + #[stable(feature = "splice", since = "1.27.0")] + pub fn replace_range(&mut self, range: R, replace_with: &str) where R: RangeBounds { // Memory safety // - // The String version of Splice does not have the memory safety issues + // Replace_range does not have the memory safety issues of a vector Splice. // of the vector version. The data is just plain bytes. match range.start() { diff --git a/src/liballoc/tests/string.rs b/src/liballoc/tests/string.rs index d1e746ea43b45..cb4a17a22d8a4 100644 --- a/src/liballoc/tests/string.rs +++ b/src/liballoc/tests/string.rs @@ -443,53 +443,53 @@ fn test_drain() { } #[test] -fn test_splice() { +fn test_replace_range() { let mut s = "Hello, world!".to_owned(); - s.splice(7..12, "世界"); + s.replace_range(7..12, "世界"); assert_eq!(s, "Hello, 世界!"); } #[test] #[should_panic] -fn test_splice_char_boundary() { +fn test_replace_range_char_boundary() { let mut s = "Hello, 世界!".to_owned(); - s.splice(..8, ""); + s.replace_range(..8, ""); } #[test] -fn test_splice_inclusive_range() { +fn test_replace_range_inclusive_range() { let mut v = String::from("12345"); - v.splice(2..=3, "789"); + v.replace_range(2..=3, "789"); assert_eq!(v, "127895"); - v.splice(1..=2, "A"); + v.replace_range(1..=2, "A"); assert_eq!(v, "1A895"); } #[test] #[should_panic] -fn test_splice_out_of_bounds() { +fn test_replace_range_out_of_bounds() { let mut s = String::from("12345"); - s.splice(5..6, "789"); + s.replace_range(5..6, "789"); } #[test] #[should_panic] -fn test_splice_inclusive_out_of_bounds() { +fn test_replace_range_inclusive_out_of_bounds() { let mut s = String::from("12345"); - s.splice(5..=5, "789"); + s.replace_range(5..=5, "789"); } #[test] -fn test_splice_empty() { +fn test_replace_range_empty() { let mut s = String::from("12345"); - s.splice(1..2, ""); + s.replace_range(1..2, ""); assert_eq!(s, "1345"); } #[test] -fn test_splice_unbounded() { +fn test_replace_range_unbounded() { let mut s = String::from("12345"); - s.splice(.., ""); + s.replace_range(.., ""); assert_eq!(s, ""); } diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 47c92028b1419..02008310b8161 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1283,6 +1283,49 @@ impl Vec { } other } + + /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. + /// + /// If `new_len` is greater than `len`, the `Vec` is extended by the + /// difference, with each additional slot filled with the result of + /// calling the closure `f`. The return values from `f` will end up + /// in the `Vec` in the order they have been generated. + /// + /// If `new_len` is less than `len`, the `Vec` is simply truncated. + /// + /// This method uses a closure to create new values on every push. If + /// you'd rather [`Clone`] a given value, use [`resize`]. If you want + /// to use the [`Default`] trait to generate values, you can pass + /// [`Default::default()`] as the second argument.. + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_resize_with)] + /// + /// let mut vec = vec![1, 2, 3]; + /// vec.resize_with(5, Default::default); + /// assert_eq!(vec, [1, 2, 3, 0, 0]); + /// + /// let mut vec = vec![]; + /// let mut p = 1; + /// vec.resize_with(4, || { p *= 2; p }); + /// assert_eq!(vec, [2, 4, 8, 16]); + /// ``` + /// + /// [`resize`]: #method.resize + /// [`Clone`]: ../../std/clone/trait.Clone.html + #[unstable(feature = "vec_resize_with", issue = "41758")] + pub fn resize_with(&mut self, new_len: usize, f: F) + where F: FnMut() -> T + { + let len = self.len(); + if new_len > len { + self.extend_with(new_len - len, ExtendFunc(f)); + } else { + self.truncate(new_len); + } + } } impl Vec { @@ -1293,8 +1336,8 @@ impl Vec { /// If `new_len` is less than `len`, the `Vec` is simply truncated. /// /// This method requires [`Clone`] to be able clone the passed value. If - /// you'd rather create a value with [`Default`] instead, see - /// [`resize_default`]. + /// you need more flexibility (or want to rely on [`Default`] instead of + /// [`Clone`]), use [`resize_with`]. /// /// # Examples /// @@ -1310,7 +1353,7 @@ impl Vec { /// /// [`Clone`]: ../../std/clone/trait.Clone.html /// [`Default`]: ../../std/default/trait.Default.html - /// [`resize_default`]: #method.resize_default + /// [`resize_with`]: #method.resize_with #[stable(feature = "vec_resize", since = "1.5.0")] pub fn resize(&mut self, new_len: usize, value: T) { let len = self.len(); @@ -1389,24 +1432,31 @@ impl Vec { // This code generalises `extend_with_{element,default}`. trait ExtendWith { - fn next(&self) -> T; + fn next(&mut self) -> T; fn last(self) -> T; } struct ExtendElement(T); impl ExtendWith for ExtendElement { - fn next(&self) -> T { self.0.clone() } + fn next(&mut self) -> T { self.0.clone() } fn last(self) -> T { self.0 } } struct ExtendDefault; impl ExtendWith for ExtendDefault { - fn next(&self) -> T { Default::default() } + fn next(&mut self) -> T { Default::default() } fn last(self) -> T { Default::default() } } + +struct ExtendFunc(F); +impl T> ExtendWith for ExtendFunc { + fn next(&mut self) -> T { (self.0)() } + fn last(mut self) -> T { (self.0)() } +} + impl Vec { /// Extend the vector by `n` values, using the given generator. - fn extend_with>(&mut self, n: usize, value: E) { + fn extend_with>(&mut self, n: usize, mut value: E) { self.reserve(n); unsafe { diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index d25f498b99efe..c175ae15d28fe 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -105,6 +105,7 @@ pub trait Clone : Sized { /// assert_eq!("Hello", hello.clone()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "cloning is often expensive and is not expected to have side effects"] fn clone(&self) -> Self; /// Performs copy-assignment from `source`. diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 62994ed15cc6d..d55219d7226e6 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -401,10 +401,9 @@ impl<'a> Arguments<'a> { /// safely be done, so no constructors are given and the fields are private /// to prevent modification. /// -/// The [`format_args!`] macro will safely create an instance of this structure -/// and pass it to a function or closure, passed as the first argument. The -/// macro validates the format string at compile-time so usage of the [`write`] -/// and [`format`] functions can be safely performed. +/// The [`format_args!`] macro will safely create an instance of this structure. +/// The macro validates the format string at compile-time so usage of the +/// [`write`] and [`format`] functions can be safely performed. /// /// You can use the `Arguments<'a>` that [`format_args!`] returns in `Debug` /// and `Display` contexts as seen below. The example also shows that `Debug` @@ -412,8 +411,8 @@ impl<'a> Arguments<'a> { /// in `format_args!`. /// /// ```rust -/// let display = format!("{:?}", format_args!("{} foo {:?}", 1, 2)); -/// let debug = format!("{}", format_args!("{} foo {:?}", 1, 2)); +/// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2)); +/// let display = format!("{}", format_args!("{} foo {:?}", 1, 2)); /// assert_eq!("1 foo 2", display); /// assert_eq!(display, debug); /// ``` diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index f039d1730eb3b..4ccf446aa6346 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -1368,6 +1368,7 @@ pub trait Iterator { /// [`Result`]: ../../std/result/enum.Result.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"] fn collect>(self) -> B where Self: Sized { FromIterator::from_iter(self) } @@ -1446,7 +1447,6 @@ pub trait Iterator { /// Basic usage: /// /// ``` - /// #![feature(iterator_try_fold)] /// let a = [1, 2, 3]; /// /// // the checked sum of all of the elements of the array @@ -1458,7 +1458,6 @@ pub trait Iterator { /// Short-circuiting: /// /// ``` - /// #![feature(iterator_try_fold)] /// let a = [10, 20, 30, 100, 40, 50]; /// let mut it = a.iter(); /// @@ -1472,7 +1471,7 @@ pub trait Iterator { /// assert_eq!(it.next(), Some(&40)); /// ``` #[inline] - #[unstable(feature = "iterator_try_fold", issue = "45594")] + #[stable(feature = "iterator_try_fold", since = "1.27.0")] fn try_fold(&mut self, init: B, mut f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try { @@ -1495,7 +1494,6 @@ pub trait Iterator { /// # Examples /// /// ``` - /// #![feature(iterator_try_fold)] /// use std::fs::rename; /// use std::io::{stdout, Write}; /// use std::path::Path; @@ -1512,7 +1510,7 @@ pub trait Iterator { /// assert_eq!(it.next(), Some("stale_bread.json")); /// ``` #[inline] - #[unstable(feature = "iterator_try_fold", issue = "45594")] + #[stable(feature = "iterator_try_fold", since = "1.27.0")] fn try_for_each(&mut self, mut f: F) -> R where Self: Sized, F: FnMut(Self::Item) -> R, R: Try { diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 72b48b565719c..5d57207763e47 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -488,6 +488,7 @@ macro_rules! try_from_unbounded { } // unsigned to signed (only positive bound) +#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] macro_rules! try_from_upper_bounded { ($($target:ty),*) => {$( impl PrivateTryFromUsize for $target { diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index c3aebc4fb23ce..ddbb59989424f 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -427,7 +427,6 @@ pub trait DoubleEndedIterator: Iterator { /// Basic usage: /// /// ``` - /// #![feature(iterator_try_fold)] /// let a = ["1", "2", "3"]; /// let sum = a.iter() /// .map(|&s| s.parse::()) @@ -438,7 +437,6 @@ pub trait DoubleEndedIterator: Iterator { /// Short-circuiting: /// /// ``` - /// #![feature(iterator_try_fold)] /// let a = ["1", "rust", "3"]; /// let mut it = a.iter(); /// let sum = it @@ -452,7 +450,7 @@ pub trait DoubleEndedIterator: Iterator { /// assert_eq!(it.next_back(), Some(&"1")); /// ``` #[inline] - #[unstable(feature = "iterator_try_fold", issue = "45594")] + #[stable(feature = "iterator_try_fold", since = "1.27.0")] fn try_rfold(&mut self, init: B, mut f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try { @@ -491,7 +489,6 @@ pub trait DoubleEndedIterator: Iterator { /// Basic usage: /// /// ``` - /// #![feature(iter_rfold)] /// let a = [1, 2, 3]; /// /// // the sum of all of the elements of a @@ -505,7 +502,6 @@ pub trait DoubleEndedIterator: Iterator { /// and continuing with each element from the back until the front: /// /// ``` - /// #![feature(iter_rfold)] /// let numbers = [1, 2, 3, 4, 5]; /// /// let zero = "0".to_string(); @@ -517,14 +513,14 @@ pub trait DoubleEndedIterator: Iterator { /// assert_eq!(result, "(1 + (2 + (3 + (4 + (5 + 0)))))"); /// ``` #[inline] - #[unstable(feature = "iter_rfold", issue = "44705")] + #[stable(feature = "iter_rfold", since = "1.27.0")] fn rfold(mut self, accum: B, mut f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { self.try_rfold(accum, move |acc, x| AlwaysOk(f(acc, x))).0 } - /// Searches for an element of an iterator from the right that satisfies a predicate. + /// Searches for an element of an iterator from the back that satisfies a predicate. /// /// `rfind()` takes a closure that returns `true` or `false`. It applies /// this closure to each element of the iterator, starting at the end, and if any @@ -547,8 +543,6 @@ pub trait DoubleEndedIterator: Iterator { /// Basic usage: /// /// ``` - /// #![feature(iter_rfind)] - /// /// let a = [1, 2, 3]; /// /// assert_eq!(a.iter().rfind(|&&x| x == 2), Some(&2)); @@ -559,8 +553,6 @@ pub trait DoubleEndedIterator: Iterator { /// Stopping at the first `true`: /// /// ``` - /// #![feature(iter_rfind)] - /// /// let a = [1, 2, 3]; /// /// let mut iter = a.iter(); @@ -571,7 +563,7 @@ pub trait DoubleEndedIterator: Iterator { /// assert_eq!(iter.next_back(), Some(&1)); /// ``` #[inline] - #[unstable(feature = "iter_rfind", issue = "39480")] + #[stable(feature = "iter_rfind", since = "1.27.0")] fn rfind

(&mut self, mut predicate: P) -> Option where Self: Sized, P: FnMut(&Self::Item) -> bool diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 6f6105553d4de..de7211e718c9f 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -25,11 +25,8 @@ #![feature(iterator_step_by)] #![cfg_attr(stage0, feature(i128_type))] #![cfg_attr(stage0, feature(inclusive_range_syntax))] -#![feature(iterator_try_fold)] #![feature(iterator_flatten)] #![cfg_attr(stage0, feature(conservative_impl_trait))] -#![feature(iter_rfind)] -#![feature(iter_rfold)] #![feature(iterator_repeat_with)] #![feature(nonzero)] #![feature(pattern)] diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 29c8ac046b815..328b2db2b5828 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -470,6 +470,30 @@ pub fn check_unstable_api_usage<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx.hir.krate().visit_all_item_likes(&mut checker.as_deep_visitor()); } +/// Check whether an item marked with `deprecated(since="X")` is currently +/// deprecated (i.e. whether X is not greater than the current rustc version). +pub fn deprecation_in_effect(since: &str) -> bool { + fn parse_version(ver: &str) -> Vec { + // We ignore non-integer components of the version (e.g. "nightly"). + ver.split(|c| c == '.' || c == '-').flat_map(|s| s.parse()).collect() + } + + if let Some(rustc) = option_env!("CFG_RELEASE") { + let since: Vec = parse_version(since); + let rustc: Vec = parse_version(rustc); + // We simply treat invalid `since` attributes as relating to a previous + // Rust version, thus always displaying the warning. + if since.len() != 3 { + return true; + } + since <= rustc + } else { + // By default, a deprecation warning applies to + // the current version of the compiler. + true + } +} + struct Checker<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, } @@ -559,9 +583,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // Deprecated attributes apply in-crate and cross-crate. if let Some(id) = id { if let Some(depr_entry) = self.lookup_deprecation_entry(def_id) { + // If the deprecation is scheduled for a future Rust + // version, then we should display no warning message. + let deprecated_in_future_version = if let Some(sym) = depr_entry.attr.since { + let since = sym.as_str(); + !deprecation_in_effect(&since) + } else { + false + }; + let parent_def_id = self.hir.local_def_id(self.hir.get_parent(id)); - let skip = self.lookup_deprecation_entry(parent_def_id) - .map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry)); + let skip = deprecated_in_future_version || + self.lookup_deprecation_entry(parent_def_id) + .map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry)); if !skip { lint_deprecated(def_id, id, depr_entry.attr.note); } diff --git a/src/librustc_data_structures/indexed_set.rs b/src/librustc_data_structures/indexed_set.rs index 7ab6a2691488e..c9495587c4687 100644 --- a/src/librustc_data_structures/indexed_set.rs +++ b/src/librustc_data_structures/indexed_set.rs @@ -121,7 +121,9 @@ impl IdxSetBuf { /// Creates set holding every element whose index falls in range 0..universe_size. pub fn new_filled(universe_size: usize) -> Self { - Self::new(!0, universe_size) + let mut result = Self::new(!0, universe_size); + result.trim_to(universe_size); + result } /// Creates set holding no elements. @@ -168,6 +170,36 @@ impl IdxSet { } } + /// Sets all elements up to `universe_size` + pub fn set_up_to(&mut self, universe_size: usize) { + for b in &mut self.bits { + *b = !0; + } + self.trim_to(universe_size); + } + + /// Clear all elements above `universe_size`. + fn trim_to(&mut self, universe_size: usize) { + let word_bits = mem::size_of::() * 8; + + // `trim_block` is the first block where some bits have + // to be cleared. + let trim_block = universe_size / word_bits; + + // all the blocks above it have to be completely cleared. + if trim_block < self.bits.len() { + for b in &mut self.bits[trim_block+1..] { + *b = 0; + } + + // at that block, the `universe_size % word_bits` lsbs + // should remain. + let remaining_bits = universe_size % word_bits; + let mask = (1< bool { self.bits.clear_bit(elem.index()) @@ -252,3 +284,43 @@ impl<'a, T: Idx> Iterator for Iter<'a, T> { } } } + +#[test] +fn test_trim_to() { + use std::cmp; + + for i in 0..256 { + let mut idx_buf: IdxSetBuf = IdxSetBuf::new_filled(128); + idx_buf.trim_to(i); + + let elems: Vec = idx_buf.iter().collect(); + let expected: Vec = (0..cmp::min(i, 128)).collect(); + assert_eq!(elems, expected); + } +} + +#[test] +fn test_set_up_to() { + for i in 0..128 { + for mut idx_buf in + vec![IdxSetBuf::new_empty(128), IdxSetBuf::new_filled(128)] + .into_iter() + { + idx_buf.set_up_to(i); + + let elems: Vec = idx_buf.iter().collect(); + let expected: Vec = (0..i).collect(); + assert_eq!(elems, expected); + } + } +} + +#[test] +fn test_new_filled() { + for i in 0..128 { + let mut idx_buf = IdxSetBuf::new_filled(i); + let elems: Vec = idx_buf.iter().collect(); + let expected: Vec = (0..i).collect(); + assert_eq!(elems, expected); + } +} diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 8494c043f90fc..6f5fcc9e421cc 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -317,7 +317,7 @@ newtype_index!(ScopeId); /// macro (and methods below) makes working with `BlockAnd` much more /// convenient. -#[must_use] // if you don't use one of these results, you're leaving a dangling edge +#[must_use = "if you don't use one of these results, you're leaving a dangling edge"] struct BlockAnd(BasicBlock, T); trait BlockAndExtension { diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index c5f5492cd2c2c..287640439c0e8 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -389,7 +389,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MaybeUninitializedPlaces<'a, 'gcx, 'tcx> // sets on_entry bits for Arg places fn start_block_effect(&self, entry_set: &mut IdxSet) { // set all bits to 1 (uninit) before gathering counterevidence - for e in entry_set.words_mut() { *e = !0; } + entry_set.set_up_to(self.bits_per_block()); drop_flag_effects_for_function_entry( self.tcx, self.mir, self.mdpe, @@ -443,7 +443,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for DefinitelyInitializedPlaces<'a, 'gcx, 'tc // sets on_entry bits for Arg places fn start_block_effect(&self, entry_set: &mut IdxSet) { - for e in entry_set.words_mut() { *e = 0; } + entry_set.clear(); drop_flag_effects_for_function_entry( self.tcx, self.mir, self.mdpe, diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index b8bfcd756cd23..cf3241fe9be66 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -743,20 +743,29 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M Discriminant(ref place) => { let ty = self.place_ty(place); + let layout = self.layout_of(ty)?; let place = self.eval_place(place)?; let discr_val = self.read_discriminant_value(place, ty)?; - if let ty::TyAdt(adt_def, _) = ty.sty { - trace!("Read discriminant {}, valid discriminants {:?}", discr_val, adt_def.discriminants(*self.tcx).collect::>()); - if adt_def.discriminants(*self.tcx).all(|v| { - discr_val != v.val - }) - { - return err!(InvalidDiscriminant); + match layout.variants { + layout::Variants::Single { index } => { + assert_eq!(discr_val, index as u128); + } + layout::Variants::Tagged { .. } | + layout::Variants::NicheFilling { .. } => { + if let ty::TyAdt(adt_def, _) = ty.sty { + trace!("Read discriminant {}, valid discriminants {:?}", discr_val, adt_def.discriminants(*self.tcx).collect::>()); + if adt_def.discriminants(*self.tcx).all(|v| { + discr_val != v.val + }) + { + return err!(InvalidDiscriminant); + } + } else { + bug!("rustc only generates Rvalue::Discriminant for enums"); + } } - self.write_primval(dest, PrimVal::Bytes(discr_val), dest_ty)?; - } else { - bug!("rustc only generates Rvalue::Discriminant for enums"); } + self.write_primval(dest, PrimVal::Bytes(discr_val), dest_ty)?; } } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 4026f52e9620d..dcf97f61545db 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -328,6 +328,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { .ok_or(EvalErrorKind::ExecuteMemory.into()) } + pub fn get_alloc_kind(&self, id: AllocId) -> Option> { + self.alloc_kind.get(&id).cloned() + } + /// For debugging, print an allocation and all allocations it points to, recursively. pub fn dump_alloc(&self, id: AllocId) { self.dump_allocs(vec![id]); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e3ba482eecfee..6ada4ccfbddc2 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1074,8 +1074,7 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option let ty = cx.resolver.borrow_mut() .with_scope(*id, |resolver| { - resolver.resolve_str_path_error(DUMMY_SP, - &path, false) + resolver.resolve_str_path_error(DUMMY_SP, &path, false) })?; match ty.def { Def::Struct(did) | Def::Union(did) | Def::Enum(did) | Def::TyAlias(did) => { @@ -1090,7 +1089,27 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option }; Ok((ty.def, Some(format!("{}.{}", out, item_name)))) } else { - Err(()) + let is_enum = match ty.def { + Def::Enum(_) => true, + _ => false, + }; + let elem = if is_enum { + cx.tcx.adt_def(did).all_fields().find(|item| item.name == item_name) + } else { + cx.tcx.adt_def(did) + .non_enum_variant() + .fields + .iter() + .find(|item| item.name == item_name) + }; + if let Some(item) = elem { + Ok((ty.def, + Some(format!("{}.{}", + if is_enum { "variant" } else { "structfield" }, + item.name)))) + } else { + Err(()) + } } } Def::Trait(did) => { @@ -1101,7 +1120,13 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option let kind = match item.kind { ty::AssociatedKind::Const if is_val => "associatedconstant", ty::AssociatedKind::Type if !is_val => "associatedtype", - ty::AssociatedKind::Method if is_val => "tymethod", + ty::AssociatedKind::Method if is_val => { + if item.defaultness.has_value() { + "method" + } else { + "tymethod" + } + } _ => return Err(()) }; diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index d915bab7919c7..8e6dcf8caf484 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2113,9 +2113,15 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec{}", text)) }; @@ -2165,7 +2171,15 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec{}", text)) } @@ -2801,10 +2815,15 @@ fn item_union(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, write!(w, "

Fields

")?; for (field, ty) in fields { - write!(w, "{name}: {ty} + let name = field.name.as_ref().expect("union field name"); + let id = format!("{}.{}", ItemType::StructField, name); + write!(w, "\ + \ + \ ", + id = id, + name = name, shortty = ItemType::StructField, - name = field.name.as_ref().unwrap(), ty = ty)?; if let Some(stability_class) = field.stability_class() { write!(w, "", diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 2d0fe55f70d26..09776569f80bf 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -239,7 +239,7 @@ a.test-arrow:hover{ } :target > code { - background: #FDFFD3; + background-color: #494a3d; } pre.compile_fail { diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 479e4d08f4b4d..7bd1adc411ae4 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -231,7 +231,9 @@ fn initial_buffer_size(file: &File) -> usize { /// Read the entire contents of a file into a bytes vector. /// /// This is a convenience function for using [`File::open`] and [`read_to_end`] -/// with fewer imports and without an intermediate variable. +/// with fewer imports and without an intermediate variable. It pre-allocates a +/// buffer based on the file size when available, so it is generally faster than +/// reading into a vector created with `Vec::new()`. /// /// [`File::open`]: struct.File.html#method.open /// [`read_to_end`]: ../io/trait.Read.html#method.read_to_end @@ -270,7 +272,9 @@ pub fn read>(path: P) -> io::Result> { /// Read the entire contents of a file into a string. /// /// This is a convenience function for using [`File::open`] and [`read_to_string`] -/// with fewer imports and without an intermediate variable. +/// with fewer imports and without an intermediate variable. It pre-allocates a +/// buffer based on the file size when available, so it is generally faster than +/// reading into a string created with `String::new()`. /// /// [`File::open`]: struct.File.html#method.open /// [`read_to_string`]: ../io/trait.Read.html#method.read_to_string diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index cefff2f143ce7..d6eac74833483 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -25,6 +25,12 @@ use memchr; /// results in a system call. A `BufReader` performs large, infrequent reads on /// the underlying [`Read`] and maintains an in-memory buffer of the results. /// +/// `BufReader` can improve the speed of programs that make *small* and +/// *repeated* read calls to the same file or network socket. It does not +/// help when reading very large amounts at once, or reading just one or a few +/// times. It also provides no advantage when reading from a source that is +/// already in memory, like a `Vec`. +/// /// [`Read`]: ../../std/io/trait.Read.html /// [`TcpStream::read`]: ../../std/net/struct.TcpStream.html#method.read /// [`TcpStream`]: ../../std/net/struct.TcpStream.html @@ -180,7 +186,7 @@ impl BufReader { /// /// # Examples /// - /// ```no_ru + /// ```no_run /// # #![feature(bufreader_buffer)] /// use std::io::{BufReader, BufRead}; /// use std::fs::File; @@ -359,6 +365,12 @@ impl Seek for BufReader { /// `BufWriter` keeps an in-memory buffer of data and writes it to an underlying /// writer in large, infrequent batches. /// +/// `BufWriter` can improve the speed of programs that make *small* and +/// *repeated* write calls to the same file or network socket. It does not +/// help when writing very large amounts at once, or writing just one or a few +/// times. It also provides no advantage when writing to a destination that is +/// in memory, like a `Vec`. +/// /// When the `BufWriter` is dropped, the contents of its buffer will be written /// out. However, any errors that happen in the process of flushing the buffer /// when the writer is dropped will be ignored. Code that wishes to handle such diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 63b631ace9693..3b8c42ddb39d8 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -595,6 +595,11 @@ pub trait Read { /// Ok(()) /// } /// ``` + /// + /// (See also the [`std::fs::read`] convenience function for reading from a + /// file.) + /// + /// [`std::fs::read`]: ../fs/fn.read.html #[stable(feature = "rust1", since = "1.0.0")] fn read_to_end(&mut self, buf: &mut Vec) -> Result { read_to_end(self, buf) @@ -633,6 +638,11 @@ pub trait Read { /// Ok(()) /// } /// ``` + /// + /// (See also the [`std::fs::read_to_string`] convenience function for + /// reading from a file.) + /// + /// [`std::fs::read_to_string`]: ../fs/fn.read_to_string.html #[stable(feature = "rust1", since = "1.0.0")] fn read_to_string(&mut self, buf: &mut String) -> Result { // Note that we do *not* call `.read_to_end()` here. We are passing diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 47609f17221ef..5ef7c15965505 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -341,8 +341,8 @@ pub mod builtin { /// format string in `format_args!`. /// /// ```rust - /// let display = format!("{:?}", format_args!("{} foo {:?}", 1, 2)); - /// let debug = format!("{}", format_args!("{} foo {:?}", 1, 2)); + /// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2)); + /// let display = format!("{}", format_args!("{} foo {:?}", 1, 2)); /// assert_eq!("1 foo 2", display); /// assert_eq!(display, debug); /// ``` diff --git a/src/libstd/process.rs b/src/libstd/process.rs index b463a6d88fe8e..40bc84f4bc104 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -1426,7 +1426,7 @@ pub fn abort() -> ! { /// ``` /// /// -#[stable(feature = "getpid", since = "1.27.0")] +#[stable(feature = "getpid", since = "1.26.0")] pub fn id() -> u32 { ::sys::os::getpid() } diff --git a/src/libstd/sys/unix/ext/process.rs b/src/libstd/sys/unix/ext/process.rs index 60309bec6d4fc..7b4ec20d91fb4 100644 --- a/src/libstd/sys/unix/ext/process.rs +++ b/src/libstd/sys/unix/ext/process.rs @@ -193,7 +193,7 @@ impl IntoRawFd for process::ChildStderr { } /// Returns the OS-assigned process identifier associated with this process's parent. -#[unstable(feature = "unix_ppid", issue = "46104")] +#[stable(feature = "unix_ppid", since = "1.27.0")] pub fn parent_id() -> u32 { ::sys::os::getppid() } diff --git a/src/test/compile-fail/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs b/src/test/compile-fail/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs index df0a05dfaee0e..f2e6d51d064d1 100644 --- a/src/test/compile-fail/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs +++ b/src/test/compile-fail/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-test will be fixed later // revisions: ast mir //[mir]compile-flags: -Z borrowck=mir diff --git a/src/test/compile-fail/deprecation-lint.rs b/src/test/compile-fail/deprecation-lint.rs index a058234a64921..93eb6b6b11544 100644 --- a/src/test/compile-fail/deprecation-lint.rs +++ b/src/test/compile-fail/deprecation-lint.rs @@ -180,6 +180,11 @@ mod this_crate { #[deprecated(since = "1.0.0", note = "text")] pub fn deprecated_text() {} + #[deprecated(since = "99.99.99", note = "text")] + pub fn deprecated_future() {} + #[deprecated(since = "99.99.99", note = "text")] + pub fn deprecated_future_text() {} + pub struct MethodTester; impl MethodTester { @@ -266,6 +271,9 @@ mod this_crate { ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text + deprecated_future(); // Fine; no error. + deprecated_future_text(); // Fine; no error. + let _ = DeprecatedStruct { //~^ ERROR use of deprecated item 'this_crate::DeprecatedStruct': text i: 0 //~ ERROR use of deprecated item 'this_crate::DeprecatedStruct::i': text diff --git a/src/test/run-pass-fulldeps/proc-macro/attr-stmt-expr.rs b/src/test/run-pass-fulldeps/proc-macro/attr-stmt-expr.rs index 082dd63992968..98316c62ef135 100644 --- a/src/test/run-pass-fulldeps/proc-macro/attr-stmt-expr.rs +++ b/src/test/run-pass-fulldeps/proc-macro/attr-stmt-expr.rs @@ -14,7 +14,8 @@ #![feature(proc_macro, stmt_expr_attributes)] extern crate attr_stmt_expr; -use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr}; +use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr, + no_output, noop}; fn print_str(string: &'static str) { // macros are handled a bit differently @@ -29,6 +30,17 @@ fn main() { #[expect_print_stmt] println!("{}", string); + let _: () = { + #[no_output] + "Hello, world!" + }; + + let _: &'static str = #[noop] "Hello, world!"; + + let _: &'static str = { + #[noop] "Hello, world!" + }; + #[expect_expr] print_str("string") } diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-stmt-expr.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-stmt-expr.rs index 189e6bbd00dba..972368b7b532a 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-stmt-expr.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-stmt-expr.rs @@ -44,3 +44,18 @@ pub fn expect_print_expr(attr: TokenStream, item: TokenStream) -> TokenStream { assert_eq!(item.to_string(), "println!(\"{}\" , string)"); item } + +#[proc_macro_attribute] +pub fn no_output(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert!(!item.to_string().is_empty()); + "".parse().unwrap() + +} + +#[proc_macro_attribute] +pub fn noop(attr: TokenStream, item: TokenStream) -> TokenStream { + assert!(attr.to_string().is_empty()); + assert!(!item.to_string().is_empty()); + item +} diff --git a/src/test/rustdoc/default-trait-method-link.rs b/src/test/rustdoc/default-trait-method-link.rs new file mode 100644 index 0000000000000..9cde446eb941e --- /dev/null +++ b/src/test/rustdoc/default-trait-method-link.rs @@ -0,0 +1,25 @@ +// Copyright 2018 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. + +#![crate_name = "foo"] + +// @has foo/trait.Foo.html '//a[@href="../foo/trait.Foo.html#tymethod.req"]' 'req' +// @has foo/trait.Foo.html '//a[@href="../foo/trait.Foo.html#method.prov"]' 'prov' + +/// Always make sure to implement [`req`], but you don't have to implement [`prov`]. +/// +/// [`req`]: Foo::req +/// [`prov`]: Foo::prov +pub trait Foo { + /// Required + fn req(); + /// Provided + fn prov() {} +} diff --git a/src/test/rustdoc/deprecated-future.rs b/src/test/rustdoc/deprecated-future.rs new file mode 100644 index 0000000000000..6feb98dad09c6 --- /dev/null +++ b/src/test/rustdoc/deprecated-future.rs @@ -0,0 +1,16 @@ +// Copyright 2018 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(deprecated)] + +// @has deprecated_future/struct.S.html '//*[@class="stab deprecated"]' \ +// 'Deprecating in 99.99.99: effectively never' +#[deprecated(since = "99.99.99", note = "effectively never")] +pub struct S; diff --git a/src/test/rustdoc/issue-32556.rs b/src/test/rustdoc/issue-32556.rs new file mode 100644 index 0000000000000..3ab138079a1f0 --- /dev/null +++ b/src/test/rustdoc/issue-32556.rs @@ -0,0 +1,15 @@ +// Copyright 2018 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. + +/// Blah blah blah +/// ```ignore (testing rustdoc's handling of ignore) +/// bad_assert!(); +/// ``` +pub fn foo() {} diff --git a/src/test/rustdoc/struct-field.rs b/src/test/rustdoc/struct-field.rs new file mode 100644 index 0000000000000..c5016bac7d394 --- /dev/null +++ b/src/test/rustdoc/struct-field.rs @@ -0,0 +1,33 @@ +// Copyright 2018 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. + +#![crate_name = "foo"] + +// ignore-tidy-linelength + +// @has foo/index.html '//*[@class="docblock"]/p/a[@href="../foo/struct.Foo.html#structfield.bar"]' 'Foo::bar' +// @has foo/index.html '//*[@class="docblock"]/p/a[@href="../foo/union.Bar.html#structfield.foo"]' 'Bar::foo' +// @has foo/index.html '//*[@class="docblock"]/p/a[@href="../foo/enum.Uniooon.html#X.v"]' 'Uniooon::X' + +//! Test with [Foo::bar], [Bar::foo], [Uniooon::X] + +pub struct Foo { + pub bar: usize, +} + +pub union Bar { + pub foo: u32, +} + +pub enum Uniooon { + F, + X, + Y, +} diff --git a/src/test/ui/nll/decl-macro-illegal-copy.rs b/src/test/ui/nll/decl-macro-illegal-copy.rs new file mode 100644 index 0000000000000..1525791c88112 --- /dev/null +++ b/src/test/ui/nll/decl-macro-illegal-copy.rs @@ -0,0 +1,39 @@ +// Copyright 2017 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. + +// Regression test for #46314 + +#![feature(nll)] +#![feature(decl_macro)] + +struct NonCopy(String); + +struct Wrapper { + inner: NonCopy, +} + +macro inner_copy($wrapper:ident) { + $wrapper.inner +} + +fn main() { + let wrapper = Wrapper { + inner: NonCopy("foo".into()), + }; + assert_two_non_copy( + inner_copy!(wrapper), + wrapper.inner, + //~^ ERROR use of moved value: `wrapper.inner` [E0382] + ); +} + +fn assert_two_non_copy(a: NonCopy, b: NonCopy) { + assert_eq!(a.0, b.0); +} diff --git a/src/test/ui/nll/decl-macro-illegal-copy.stderr b/src/test/ui/nll/decl-macro-illegal-copy.stderr new file mode 100644 index 0000000000000..8bc25c23e0178 --- /dev/null +++ b/src/test/ui/nll/decl-macro-illegal-copy.stderr @@ -0,0 +1,14 @@ +error[E0382]: use of moved value: `wrapper.inner` + --> $DIR/decl-macro-illegal-copy.rs:32:9 + | +LL | $wrapper.inner + | -------------- value moved here +... +LL | wrapper.inner, + | ^^^^^^^^^^^^^ value used here after move + | + = note: move occurs because `wrapper.inner` has type `NonCopy`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/nll/issue-43058.rs b/src/test/ui/nll/issue-43058.rs new file mode 100644 index 0000000000000..91ac7e4004260 --- /dev/null +++ b/src/test/ui/nll/issue-43058.rs @@ -0,0 +1,38 @@ +// Copyright 2017 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. + +// must-compile-successfully + +#![feature(nll)] + +use std::borrow::Cow; + +#[derive(Clone, Debug)] +struct S<'a> { + name: Cow<'a, str> +} + +#[derive(Clone, Debug)] +struct T<'a> { + s: Cow<'a, [S<'a>]> +} + +fn main() { + let s1 = [S { name: Cow::Borrowed("Test1") }, S { name: Cow::Borrowed("Test2") }]; + let b1 = T { s: Cow::Borrowed(&s1) }; + let s2 = [S { name: Cow::Borrowed("Test3") }, S { name: Cow::Borrowed("Test4") }]; + let b2 = T { s: Cow::Borrowed(&s2) }; + + let mut v = Vec::new(); + v.push(b1); + v.push(b2); + + println!("{:?}", v); +} diff --git a/src/tools/cargo b/src/tools/cargo index d63299b6eafae..b70ab13b31628 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit d63299b6eafae99bfe1fd5ddc75bc7cf67ed58f9 +Subproject commit b70ab13b31628e91b05961d55c07abf20ad49de6