diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index c61e3183409f2..b2789a535fe49 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -29,10 +29,8 @@ //! Nil, //! } //! -//! fn main() { -//! let list: List = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil)))); -//! println!("{:?}", list); -//! } +//! let list: List = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil)))); +//! println!("{:?}", list); //! ``` //! //! This will print `Cons(1, Cons(2, Nil))`. @@ -375,14 +373,12 @@ impl Box { /// ``` /// #![feature(box_into_raw_non_null)] /// - /// fn main() { - /// let x = Box::new(5); - /// let ptr = Box::into_raw_non_null(x); + /// let x = Box::new(5); + /// let ptr = Box::into_raw_non_null(x); /// - /// // Clean up the memory by converting the NonNull pointer back - /// // into a Box and letting the Box be dropped. - /// let x = unsafe { Box::from_raw(ptr.as_ptr()) }; - /// } + /// // Clean up the memory by converting the NonNull pointer back + /// // into a Box and letting the Box be dropped. + /// let x = unsafe { Box::from_raw(ptr.as_ptr()) }; /// ``` #[unstable(feature = "box_into_raw_non_null", issue = "47336")] #[inline] @@ -428,23 +424,19 @@ impl Box { /// Simple usage: /// /// ``` - /// fn main() { - /// let x = Box::new(41); - /// let static_ref: &'static mut usize = Box::leak(x); - /// *static_ref += 1; - /// assert_eq!(*static_ref, 42); - /// } + /// let x = Box::new(41); + /// let static_ref: &'static mut usize = Box::leak(x); + /// *static_ref += 1; + /// assert_eq!(*static_ref, 42); /// ``` /// /// Unsized data: /// /// ``` - /// fn main() { - /// let x = vec![1, 2, 3].into_boxed_slice(); - /// let static_ref = Box::leak(x); - /// static_ref[0] = 4; - /// assert_eq!(*static_ref, [4, 2, 3]); - /// } + /// let x = vec![1, 2, 3].into_boxed_slice(); + /// let static_ref = Box::leak(x); + /// static_ref[0] = 4; + /// assert_eq!(*static_ref, [4, 2, 3]); /// ``` #[stable(feature = "box_leak", since = "1.26.0")] #[inline] @@ -780,11 +772,9 @@ impl Box { /// } /// } /// - /// fn main() { - /// let my_string = "Hello World".to_string(); - /// print_if_string(Box::new(my_string)); - /// print_if_string(Box::new(0i8)); - /// } + /// let my_string = "Hello World".to_string(); + /// print_if_string(Box::new(my_string)); + /// print_if_string(Box::new(0i8)); /// ``` pub fn downcast(self) -> Result, Box> { if self.is::() { @@ -814,11 +804,9 @@ impl Box { /// } /// } /// - /// fn main() { - /// let my_string = "Hello World".to_string(); - /// print_if_string(Box::new(my_string)); - /// print_if_string(Box::new(0i8)); - /// } + /// let my_string = "Hello World".to_string(); + /// print_if_string(Box::new(my_string)); + /// print_if_string(Box::new(0i8)); /// ``` pub fn downcast(self) -> Result, Box> { >::downcast(self).map_err(|s| unsafe { diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index ddf012d15029a..83fd4485f7321 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -2226,14 +2226,12 @@ impl<'a, K: Ord, V: Default> Entry<'a, K, V> { /// # Examples /// /// ``` - /// # fn main() { /// use std::collections::BTreeMap; /// /// let mut map: BTreeMap<&str, Option> = BTreeMap::new(); /// map.entry("poneyland").or_default(); /// /// assert_eq!(map["poneyland"], None); - /// # } /// ``` pub fn or_default(self) -> &'a mut V { match self { diff --git a/src/liballoc/collections/btree/set.rs b/src/liballoc/collections/btree/set.rs index 0cb91ba4c81da..8250fc38ccd1c 100644 --- a/src/liballoc/collections/btree/set.rs +++ b/src/liballoc/collections/btree/set.rs @@ -122,13 +122,16 @@ pub struct Difference<'a, T: 'a> { } enum DifferenceInner<'a, T: 'a> { Stitch { + // iterate all of self and some of other, spotting matches along the way self_iter: Iter<'a, T>, other_iter: Peekable>, }, Search { + // iterate a small set, look up in the large set self_iter: Iter<'a, T>, other_set: &'a BTreeSet, }, + Iterate(Iter<'a, T>), // simply stream self's elements } #[stable(feature = "collection_debug", since = "1.17.0")] @@ -147,6 +150,7 @@ impl fmt::Debug for Difference<'_, T> { self_iter, other_set: _, } => f.debug_tuple("Difference").field(&self_iter).finish(), + DifferenceInner::Iterate(iter) => f.debug_tuple("Difference").field(&iter).finish(), } } } @@ -187,13 +191,16 @@ pub struct Intersection<'a, T: 'a> { } enum IntersectionInner<'a, T: 'a> { Stitch { + // iterate similarly sized sets jointly, spotting matches along the way a: Iter<'a, T>, b: Iter<'a, T>, }, Search { + // iterate a small set, look up in the large set small_iter: Iter<'a, T>, large_set: &'a BTreeSet, }, + Answer(Option<&'a T>), // return a specific value or emptiness } #[stable(feature = "collection_debug", since = "1.17.0")] @@ -212,6 +219,9 @@ impl fmt::Debug for Intersection<'_, T> { small_iter, large_set: _, } => f.debug_tuple("Intersection").field(&small_iter).finish(), + IntersectionInner::Answer(answer) => { + f.debug_tuple("Intersection").field(&answer).finish() + } } } } @@ -314,24 +324,51 @@ impl BTreeSet { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn difference<'a>(&'a self, other: &'a BTreeSet) -> Difference<'a, T> { - if self.len() > other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF { - // Self is bigger than or not much smaller than other set. - // Iterate both sets jointly, spotting matches along the way. - Difference { - inner: DifferenceInner::Stitch { - self_iter: self.iter(), - other_iter: other.iter().peekable(), - }, - } + let (self_min, self_max) = if let (Some(self_min), Some(self_max)) = + (self.iter().next(), self.iter().next_back()) + { + (self_min, self_max) } else { - // Self is much smaller than other set, or both sets are empty. - // Iterate the small set, searching for matches in the large set. - Difference { - inner: DifferenceInner::Search { - self_iter: self.iter(), - other_set: other, - }, - } + return Difference { + inner: DifferenceInner::Iterate(self.iter()), + }; + }; + let (other_min, other_max) = if let (Some(other_min), Some(other_max)) = + (other.iter().next(), other.iter().next_back()) + { + (other_min, other_max) + } else { + return Difference { + inner: DifferenceInner::Iterate(self.iter()), + }; + }; + Difference { + inner: match (self_min.cmp(other_max), self_max.cmp(other_min)) { + (Greater, _) | (_, Less) => DifferenceInner::Iterate(self.iter()), + (Equal, _) => { + let mut self_iter = self.iter(); + self_iter.next(); + DifferenceInner::Iterate(self_iter) + } + (_, Equal) => { + let mut self_iter = self.iter(); + self_iter.next_back(); + DifferenceInner::Iterate(self_iter) + } + _ => { + if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF { + DifferenceInner::Search { + self_iter: self.iter(), + other_set: other, + } + } else { + DifferenceInner::Stitch { + self_iter: self.iter(), + other_iter: other.iter().peekable(), + } + } + } + }, } } @@ -387,29 +424,48 @@ impl BTreeSet { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn intersection<'a>(&'a self, other: &'a BTreeSet) -> Intersection<'a, T> { - let (small, other) = if self.len() <= other.len() { - (self, other) + let (self_min, self_max) = if let (Some(self_min), Some(self_max)) = + (self.iter().next(), self.iter().next_back()) + { + (self_min, self_max) } else { - (other, self) + return Intersection { + inner: IntersectionInner::Answer(None), + }; }; - if small.len() > other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF { - // Small set is not much smaller than other set. - // Iterate both sets jointly, spotting matches along the way. - Intersection { - inner: IntersectionInner::Stitch { - a: small.iter(), - b: other.iter(), - }, - } + let (other_min, other_max) = if let (Some(other_min), Some(other_max)) = + (other.iter().next(), other.iter().next_back()) + { + (other_min, other_max) } else { - // Big difference in number of elements, or both sets are empty. - // Iterate the small set, searching for matches in the large set. - Intersection { - inner: IntersectionInner::Search { - small_iter: small.iter(), - large_set: other, - }, - } + return Intersection { + inner: IntersectionInner::Answer(None), + }; + }; + Intersection { + inner: match (self_min.cmp(other_max), self_max.cmp(other_min)) { + (Greater, _) | (_, Less) => IntersectionInner::Answer(None), + (Equal, _) => IntersectionInner::Answer(Some(self_min)), + (_, Equal) => IntersectionInner::Answer(Some(self_max)), + _ => { + if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF { + IntersectionInner::Search { + small_iter: self.iter(), + large_set: other, + } + } else if other.len() <= self.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF { + IntersectionInner::Search { + small_iter: other.iter(), + large_set: self, + } + } else { + IntersectionInner::Stitch { + a: self.iter(), + b: other.iter(), + } + } + } + }, } } @@ -544,43 +600,61 @@ impl BTreeSet { #[stable(feature = "rust1", since = "1.0.0")] pub fn is_subset(&self, other: &BTreeSet) -> bool { // Same result as self.difference(other).next().is_none() - // but the 3 paths below are faster (in order: hugely, 20%, 5%). + // but the code below is faster (hugely in some cases). if self.len() > other.len() { - false - } else if self.len() > other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF { - // Self is not much smaller than other set. - // Stolen from TreeMap - let mut x = self.iter(); - let mut y = other.iter(); - let mut a = x.next(); - let mut b = y.next(); - while a.is_some() { - if b.is_none() { + return false; + } + let (self_min, self_max) = if let (Some(self_min), Some(self_max)) = + (self.iter().next(), self.iter().next_back()) + { + (self_min, self_max) + } else { + return true; // self is empty + }; + let (other_min, other_max) = if let (Some(other_min), Some(other_max)) = + (other.iter().next(), other.iter().next_back()) + { + (other_min, other_max) + } else { + return false; // other is empty + }; + let mut self_iter = self.iter(); + match self_min.cmp(other_min) { + Less => return false, + Equal => { + self_iter.next(); + } + Greater => (), + } + match self_max.cmp(other_max) { + Greater => return false, + Equal => { + self_iter.next_back(); + } + Less => (), + } + if self_iter.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF { + // Big difference in number of elements. + for next in self_iter { + if !other.contains(next) { return false; } - - let a1 = a.unwrap(); - let b1 = b.unwrap(); - - match b1.cmp(a1) { - Less => (), - Greater => return false, - Equal => a = x.next(), - } - - b = y.next(); } - true } else { - // Big difference in number of elements, or both sets are empty. - // Iterate the small set, searching for matches in the large set. - for next in self { - if !other.contains(next) { - return false; + // Self is not much smaller than other set. + let mut other_iter = other.iter(); + other_iter.next(); + other_iter.next_back(); + let mut self_next = self_iter.next(); + while let Some(self1) = self_next { + match other_iter.next().map_or(Less, |other1| self1.cmp(other1)) { + Less => return false, + Equal => self_next = self_iter.next(), + Greater => (), } } - true } + true } /// Returns `true` if the set is a superset of another, @@ -1120,6 +1194,7 @@ impl Clone for Difference<'_, T> { self_iter: self_iter.clone(), other_set, }, + DifferenceInner::Iterate(iter) => DifferenceInner::Iterate(iter.clone()), }, } } @@ -1138,7 +1213,7 @@ impl<'a, T: Ord> Iterator for Difference<'a, T> { loop { match other_iter .peek() - .map_or(Less, |other_next| Ord::cmp(self_next, other_next)) + .map_or(Less, |other_next| self_next.cmp(other_next)) { Less => return Some(self_next), Equal => { @@ -1160,6 +1235,7 @@ impl<'a, T: Ord> Iterator for Difference<'a, T> { return Some(self_next); } }, + DifferenceInner::Iterate(iter) => iter.next(), } } @@ -1167,12 +1243,13 @@ impl<'a, T: Ord> Iterator for Difference<'a, T> { let (self_len, other_len) = match &self.inner { DifferenceInner::Stitch { self_iter, - other_iter + other_iter, } => (self_iter.len(), other_iter.len()), DifferenceInner::Search { self_iter, - other_set + other_set, } => (self_iter.len(), other_set.len()), + DifferenceInner::Iterate(iter) => (iter.len(), 0), }; (self_len.saturating_sub(other_len), Some(self_len)) } @@ -1234,6 +1311,7 @@ impl Clone for Intersection<'_, T> { small_iter: small_iter.clone(), large_set, }, + IntersectionInner::Answer(answer) => IntersectionInner::Answer(answer.clone()), }, } } @@ -1251,7 +1329,7 @@ impl<'a, T: Ord> Iterator for Intersection<'a, T> { let mut a_next = a.next()?; let mut b_next = b.next()?; loop { - match Ord::cmp(a_next, b_next) { + match a_next.cmp(b_next) { Less => a_next = a.next()?, Greater => b_next = b.next()?, Equal => return Some(a_next), @@ -1267,15 +1345,17 @@ impl<'a, T: Ord> Iterator for Intersection<'a, T> { return Some(small_next); } }, + IntersectionInner::Answer(answer) => answer.take(), } } fn size_hint(&self) -> (usize, Option) { - let min_len = match &self.inner { - IntersectionInner::Stitch { a, b } => min(a.len(), b.len()), - IntersectionInner::Search { small_iter, .. } => small_iter.len(), - }; - (0, Some(min_len)) + match &self.inner { + IntersectionInner::Stitch { a, b } => (0, Some(min(a.len(), b.len()))), + IntersectionInner::Search { small_iter, .. } => (0, Some(small_iter.len())), + IntersectionInner::Answer(None) => (0, Some(0)), + IntersectionInner::Answer(Some(_)) => (1, Some(1)), + } } } diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index f234ac5ebe51b..a28c6d22abb95 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -861,11 +861,9 @@ impl Rc { /// } /// } /// - /// fn main() { - /// let my_string = "Hello World".to_string(); - /// print_if_string(Rc::new(my_string)); - /// print_if_string(Rc::new(0i8)); - /// } + /// let my_string = "Hello World".to_string(); + /// print_if_string(Rc::new(my_string)); + /// print_if_string(Rc::new(0i8)); /// ``` pub fn downcast(self) -> Result, Rc> { if (*self).is::() { diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 881d499c0745b..4e4a285c21dab 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -412,20 +412,15 @@ impl [T] { /// /// ``` /// #![feature(repeat_generic_slice)] - /// - /// fn main() { - /// assert_eq!([1, 2].repeat(3), vec![1, 2, 1, 2, 1, 2]); - /// } + /// assert_eq!([1, 2].repeat(3), vec![1, 2, 1, 2, 1, 2]); /// ``` /// /// A panic upon overflow: /// /// ```should_panic /// #![feature(repeat_generic_slice)] - /// fn main() { - /// // this will panic at runtime - /// b"0123456789abcdef".repeat(usize::max_value()); - /// } + /// // this will panic at runtime + /// b"0123456789abcdef".repeat(usize::max_value()); /// ``` #[unstable(feature = "repeat_generic_slice", reason = "it's on str, why not on slice?", diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index 9a1342c30d502..9231c2d3f1d56 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -500,10 +500,8 @@ impl str { /// A panic upon overflow: /// /// ```should_panic - /// fn main() { - /// // this will panic at runtime - /// "0123456789abcdef".repeat(usize::max_value()); - /// } + /// // this will panic at runtime + /// "0123456789abcdef".repeat(usize::max_value()); /// ``` #[stable(feature = "repeat_str", since = "1.16.0")] pub fn repeat(&self, n: usize) -> String { diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index abe50fdb7a396..639124e26cc20 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -164,10 +164,8 @@ use crate::vec::Vec; /// /// fn example_func(example_arg: A) {} /// -/// fn main() { -/// let example_string = String::from("example_string"); -/// example_func(&example_string); -/// } +/// let example_string = String::from("example_string"); +/// example_func(&example_string); /// ``` /// /// There are two options that would work instead. The first would be to diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 45f98162e4cd5..5977e69b7fa0f 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -1244,11 +1244,9 @@ impl Arc { /// } /// } /// - /// fn main() { - /// let my_string = "Hello World".to_string(); - /// print_if_string(Arc::new(my_string)); - /// print_if_string(Arc::new(0i8)); - /// } + /// let my_string = "Hello World".to_string(); + /// print_if_string(Arc::new(my_string)); + /// print_if_string(Arc::new(0i8)); /// ``` pub fn downcast(self) -> Result, Self> where diff --git a/src/liballoc/tests/btree/set.rs b/src/liballoc/tests/btree/set.rs index 35db18c39c83a..5c611fd21d21b 100644 --- a/src/liballoc/tests/btree/set.rs +++ b/src/liballoc/tests/btree/set.rs @@ -48,7 +48,9 @@ fn check(a: &[i32], b: &[i32], expected: &[i32], f: F) f(&set_a, &set_b, &mut |&x| { - assert_eq!(x, expected[i]); + if i < expected.len() { + assert_eq!(x, expected[i]); + } i += 1; true }); @@ -74,20 +76,20 @@ fn test_intersection() { return; } - let large = (0..1000).collect::>(); + let large = (0..100).collect::>(); check_intersection(&[], &large, &[]); check_intersection(&large, &[], &[]); check_intersection(&[-1], &large, &[]); check_intersection(&large, &[-1], &[]); check_intersection(&[0], &large, &[0]); check_intersection(&large, &[0], &[0]); - check_intersection(&[999], &large, &[999]); - check_intersection(&large, &[999], &[999]); - check_intersection(&[1000], &large, &[]); - check_intersection(&large, &[1000], &[]); - check_intersection(&[11, 5000, 1, 3, 77, 8924, 103], + check_intersection(&[99], &large, &[99]); + check_intersection(&large, &[99], &[99]); + check_intersection(&[100], &large, &[]); + check_intersection(&large, &[100], &[]); + check_intersection(&[11, 5000, 1, 3, 77, 8924], &large, - &[1, 3, 11, 77, 103]); + &[1, 3, 11, 77]); } #[test] @@ -95,10 +97,15 @@ fn test_intersection_size_hint() { let x: BTreeSet = [3, 4].iter().copied().collect(); let y: BTreeSet = [1, 2, 3].iter().copied().collect(); let mut iter = x.intersection(&y); - assert_eq!(iter.size_hint(), (0, Some(2))); + assert_eq!(iter.size_hint(), (1, Some(1))); assert_eq!(iter.next(), Some(&3)); assert_eq!(iter.size_hint(), (0, Some(0))); assert_eq!(iter.next(), None); + + iter = y.intersection(&y); + assert_eq!(iter.size_hint(), (0, Some(3))); + assert_eq!(iter.next(), Some(&1)); + assert_eq!(iter.size_hint(), (0, Some(2))); } #[test] @@ -111,6 +118,9 @@ fn test_difference() { check_difference(&[1, 12], &[], &[1, 12]); check_difference(&[], &[1, 2, 3, 9], &[]); check_difference(&[1, 3, 5, 9, 11], &[3, 9], &[1, 5, 11]); + check_difference(&[1, 3, 5, 9, 11], &[3, 6, 9], &[1, 5, 11]); + check_difference(&[1, 3, 5, 9, 11], &[0, 1], &[3, 5, 9, 11]); + check_difference(&[1, 3, 5, 9, 11], &[11, 12], &[1, 3, 5, 9]); check_difference(&[-5, 11, 22, 33, 40, 42], &[-12, -5, 14, 23, 34, 38, 39, 50], &[11, 22, 33, 40, 42]); @@ -119,18 +129,82 @@ fn test_difference() { return; } - let large = (0..1000).collect::>(); + let large = (0..100).collect::>(); check_difference(&[], &large, &[]); check_difference(&[-1], &large, &[-1]); check_difference(&[0], &large, &[]); - check_difference(&[999], &large, &[]); - check_difference(&[1000], &large, &[1000]); - check_difference(&[11, 5000, 1, 3, 77, 8924, 103], + check_difference(&[99], &large, &[]); + check_difference(&[100], &large, &[100]); + check_difference(&[11, 5000, 1, 3, 77, 8924], &large, &[5000, 8924]); check_difference(&large, &[], &large); check_difference(&large, &[-1], &large); - check_difference(&large, &[1000], &large); + check_difference(&large, &[100], &large); +} + +#[test] +fn test_difference_size_hint() { + let s246: BTreeSet = [2, 4, 6].iter().copied().collect(); + let s23456: BTreeSet = (2..=6).collect(); + let mut iter = s246.difference(&s23456); + assert_eq!(iter.size_hint(), (0, Some(3))); + assert_eq!(iter.next(), None); + + let s12345: BTreeSet = (1..=5).collect(); + iter = s246.difference(&s12345); + assert_eq!(iter.size_hint(), (0, Some(3))); + assert_eq!(iter.next(), Some(&6)); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + + let s34567: BTreeSet = (3..=7).collect(); + iter = s246.difference(&s34567); + assert_eq!(iter.size_hint(), (0, Some(3))); + assert_eq!(iter.next(), Some(&2)); + assert_eq!(iter.size_hint(), (0, Some(2))); + assert_eq!(iter.next(), None); + + let s1: BTreeSet = (-9..=1).collect(); + iter = s246.difference(&s1); + assert_eq!(iter.size_hint(), (3, Some(3))); + + let s2: BTreeSet = (-9..=2).collect(); + iter = s246.difference(&s2); + assert_eq!(iter.size_hint(), (2, Some(2))); + assert_eq!(iter.next(), Some(&4)); + assert_eq!(iter.size_hint(), (1, Some(1))); + + let s23: BTreeSet = (2..=3).collect(); + iter = s246.difference(&s23); + assert_eq!(iter.size_hint(), (1, Some(3))); + assert_eq!(iter.next(), Some(&4)); + assert_eq!(iter.size_hint(), (1, Some(1))); + + let s4: BTreeSet = (4..=4).collect(); + iter = s246.difference(&s4); + assert_eq!(iter.size_hint(), (2, Some(3))); + assert_eq!(iter.next(), Some(&2)); + assert_eq!(iter.size_hint(), (1, Some(2))); + assert_eq!(iter.next(), Some(&6)); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + + let s56: BTreeSet = (5..=6).collect(); + iter = s246.difference(&s56); + assert_eq!(iter.size_hint(), (1, Some(3))); + assert_eq!(iter.next(), Some(&2)); + assert_eq!(iter.size_hint(), (0, Some(2))); + + let s6: BTreeSet = (6..=19).collect(); + iter = s246.difference(&s6); + assert_eq!(iter.size_hint(), (2, Some(2))); + assert_eq!(iter.next(), Some(&2)); + assert_eq!(iter.size_hint(), (1, Some(1))); + + let s7: BTreeSet = (7..=19).collect(); + iter = s246.difference(&s7); + assert_eq!(iter.size_hint(), (3, Some(3))); } #[test] @@ -188,23 +262,23 @@ fn test_is_subset() { assert_eq!(is_subset(&[1, 2], &[1, 2]), true); assert_eq!(is_subset(&[1, 2], &[2, 3]), false); assert_eq!(is_subset(&[-5, 11, 22, 33, 40, 42], - &[-12, -5, 14, 23, 11, 34, 22, 38, 33, 42, 39, 40]), + &[-12, -5, 11, 14, 22, 23, 33, 34, 38, 39, 40, 42]), true); assert_eq!(is_subset(&[-5, 11, 22, 33, 40, 42], - &[-12, -5, 14, 23, 34, 38, 22, 11]), + &[-12, -5, 11, 14, 22, 23, 34, 38]), false); if cfg!(miri) { // Miri is too slow return; } - let large = (0..1000).collect::>(); + let large = (0..100).collect::>(); assert_eq!(is_subset(&[], &large), true); assert_eq!(is_subset(&large, &[]), false); assert_eq!(is_subset(&[-1], &large), false); assert_eq!(is_subset(&[0], &large), true); assert_eq!(is_subset(&[1, 2], &large), true); - assert_eq!(is_subset(&[999, 1000], &large), false); + assert_eq!(is_subset(&[99, 100], &large), false); } #[test] diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 7c6ded08bbae9..6350b189c5faa 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -389,28 +389,26 @@ impl Vec { /// use std::ptr; /// use std::mem; /// - /// fn main() { - /// let mut v = vec![1, 2, 3]; - /// - /// // Pull out the various important pieces of information about `v` - /// let p = v.as_mut_ptr(); - /// let len = v.len(); - /// let cap = v.capacity(); + /// let mut v = vec![1, 2, 3]; /// - /// unsafe { - /// // Cast `v` into the void: no destructor run, so we are in - /// // complete control of the allocation to which `p` points. - /// mem::forget(v); + /// // Pull out the various important pieces of information about `v` + /// let p = v.as_mut_ptr(); + /// let len = v.len(); + /// let cap = v.capacity(); /// - /// // Overwrite memory with 4, 5, 6 - /// for i in 0..len as isize { - /// ptr::write(p.offset(i), 4 + i); - /// } + /// unsafe { + /// // Cast `v` into the void: no destructor run, so we are in + /// // complete control of the allocation to which `p` points. + /// mem::forget(v); /// - /// // Put everything back together into a Vec - /// let rebuilt = Vec::from_raw_parts(p, len, cap); - /// assert_eq!(rebuilt, [4, 5, 6]); + /// // Overwrite memory with 4, 5, 6 + /// for i in 0..len as isize { + /// ptr::write(p.offset(i), 4 + i); /// } + /// + /// // Put everything back together into a Vec + /// let rebuilt = Vec::from_raw_parts(p, len, cap); + /// assert_eq!(rebuilt, [4, 5, 6]); /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -1391,12 +1389,10 @@ impl Vec { /// ``` /// #![feature(vec_leak)] /// - /// fn main() { - /// let x = vec![1, 2, 3]; - /// let static_ref: &'static mut [usize] = Vec::leak(x); - /// static_ref[0] += 1; - /// assert_eq!(static_ref, &[2, 2, 3]); - /// } + /// let x = vec![1, 2, 3]; + /// let static_ref: &'static mut [usize] = Vec::leak(x); + /// static_ref[0] += 1; + /// assert_eq!(static_ref, &[2, 2, 3]); /// ``` #[unstable(feature = "vec_leak", issue = "62195")] #[inline] diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 0afbf4f134679..85b59162620fa 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -87,10 +87,8 @@ pub trait Any: 'static { /// TypeId::of::() == s.type_id() /// } /// - /// fn main() { - /// assert_eq!(is_string(&0), false); - /// assert_eq!(is_string(&"cookie monster".to_string()), true); - /// } + /// assert_eq!(is_string(&0), false); + /// assert_eq!(is_string(&"cookie monster".to_string()), true); /// ``` #[stable(feature = "get_type_id", since = "1.34.0")] fn type_id(&self) -> TypeId; @@ -145,10 +143,8 @@ impl dyn Any { /// } /// } /// - /// fn main() { - /// is_string(&0); - /// is_string(&"cookie monster".to_string()); - /// } + /// is_string(&0); + /// is_string(&"cookie monster".to_string()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -179,10 +175,8 @@ impl dyn Any { /// } /// } /// - /// fn main() { - /// print_if_string(&0); - /// print_if_string(&"cookie monster".to_string()); - /// } + /// print_if_string(&0); + /// print_if_string(&"cookie monster".to_string()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -210,16 +204,14 @@ impl dyn Any { /// } /// } /// - /// fn main() { - /// let mut x = 10u32; - /// let mut s = "starlord".to_string(); + /// let mut x = 10u32; + /// let mut s = "starlord".to_string(); /// - /// modify_if_u32(&mut x); - /// modify_if_u32(&mut s); + /// modify_if_u32(&mut x); + /// modify_if_u32(&mut s); /// - /// assert_eq!(x, 42); - /// assert_eq!(&s, "starlord"); - /// } + /// assert_eq!(x, 42); + /// assert_eq!(&s, "starlord"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -250,10 +242,8 @@ impl dyn Any+Send { /// } /// } /// - /// fn main() { - /// is_string(&0); - /// is_string(&"cookie monster".to_string()); - /// } + /// is_string(&0); + /// is_string(&"cookie monster".to_string()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -276,10 +266,8 @@ impl dyn Any+Send { /// } /// } /// - /// fn main() { - /// print_if_string(&0); - /// print_if_string(&"cookie monster".to_string()); - /// } + /// print_if_string(&0); + /// print_if_string(&"cookie monster".to_string()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -300,16 +288,14 @@ impl dyn Any+Send { /// } /// } /// - /// fn main() { - /// let mut x = 10u32; - /// let mut s = "starlord".to_string(); + /// let mut x = 10u32; + /// let mut s = "starlord".to_string(); /// - /// modify_if_u32(&mut x); - /// modify_if_u32(&mut s); + /// modify_if_u32(&mut x); + /// modify_if_u32(&mut s); /// - /// assert_eq!(x, 42); - /// assert_eq!(&s, "starlord"); - /// } + /// assert_eq!(x, 42); + /// assert_eq!(&s, "starlord"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -334,10 +320,8 @@ impl dyn Any+Send+Sync { /// } /// } /// - /// fn main() { - /// is_string(&0); - /// is_string(&"cookie monster".to_string()); - /// } + /// is_string(&0); + /// is_string(&"cookie monster".to_string()); /// ``` #[stable(feature = "any_send_sync_methods", since = "1.28.0")] #[inline] @@ -360,10 +344,8 @@ impl dyn Any+Send+Sync { /// } /// } /// - /// fn main() { - /// print_if_string(&0); - /// print_if_string(&"cookie monster".to_string()); - /// } + /// print_if_string(&0); + /// print_if_string(&"cookie monster".to_string()); /// ``` #[stable(feature = "any_send_sync_methods", since = "1.28.0")] #[inline] @@ -384,16 +366,14 @@ impl dyn Any+Send+Sync { /// } /// } /// - /// fn main() { - /// let mut x = 10u32; - /// let mut s = "starlord".to_string(); + /// let mut x = 10u32; + /// let mut s = "starlord".to_string(); /// - /// modify_if_u32(&mut x); - /// modify_if_u32(&mut s); + /// modify_if_u32(&mut x); + /// modify_if_u32(&mut s); /// - /// assert_eq!(x, 42); - /// assert_eq!(&s, "starlord"); - /// } + /// assert_eq!(x, 42); + /// assert_eq!(&s, "starlord"); /// ``` #[stable(feature = "any_send_sync_methods", since = "1.28.0")] #[inline] @@ -437,10 +417,8 @@ impl TypeId { /// TypeId::of::() == TypeId::of::() /// } /// - /// fn main() { - /// assert_eq!(is_string(&0), false); - /// assert_eq!(is_string(&"cookie monster".to_string()), true); - /// } + /// assert_eq!(is_string(&0), false); + /// assert_eq!(is_string(&"cookie monster".to_string()), true); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature="const_type_id")] diff --git a/src/libcore/char/convert.rs b/src/libcore/char/convert.rs index 0a870c67518c7..c456e14db12d4 100644 --- a/src/libcore/char/convert.rs +++ b/src/libcore/char/convert.rs @@ -111,11 +111,9 @@ impl From for u32 { /// ``` /// use std::mem; /// - /// fn main() { - /// let c = 'c'; - /// let u = u32::from(c); - /// assert!(4 == mem::size_of_val(&u)) - /// } + /// let c = 'c'; + /// let u = u32::from(c); + /// assert!(4 == mem::size_of_val(&u)) /// ``` #[inline] fn from(c: char) -> Self { @@ -150,11 +148,9 @@ impl From for char { /// ``` /// use std::mem; /// - /// fn main() { - /// let u = 32 as u8; - /// let c = char::from(u); - /// assert!(4 == mem::size_of_val(&c)) - /// } + /// let u = 32 as u8; + /// let c = char::from(u); + /// assert!(4 == mem::size_of_val(&c)) /// ``` #[inline] fn from(i: u8) -> Self { diff --git a/src/libcore/char/decode.rs b/src/libcore/char/decode.rs index 23059243c61d7..b71c9c2c40b37 100644 --- a/src/libcore/char/decode.rs +++ b/src/libcore/char/decode.rs @@ -31,21 +31,23 @@ pub struct DecodeUtf16Error { /// ``` /// use std::char::decode_utf16; /// -/// fn main() { -/// // 𝄞music -/// let v = [0xD834, 0xDD1E, 0x006d, 0x0075, -/// 0x0073, 0xDD1E, 0x0069, 0x0063, -/// 0xD834]; +/// // 𝄞music +/// let v = [ +/// 0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834, +/// ]; /// -/// assert_eq!(decode_utf16(v.iter().cloned()) -/// .map(|r| r.map_err(|e| e.unpaired_surrogate())) -/// .collect::>(), -/// vec![Ok('𝄞'), -/// Ok('m'), Ok('u'), Ok('s'), -/// Err(0xDD1E), -/// Ok('i'), Ok('c'), -/// Err(0xD834)]); -/// } +/// assert_eq!( +/// decode_utf16(v.iter().cloned()) +/// .map(|r| r.map_err(|e| e.unpaired_surrogate())) +/// .collect::>(), +/// vec![ +/// Ok('𝄞'), +/// Ok('m'), Ok('u'), Ok('s'), +/// Err(0xDD1E), +/// Ok('i'), Ok('c'), +/// Err(0xD834) +/// ] +/// ); /// ``` /// /// A lossy decoder can be obtained by replacing `Err` results with the replacement character: @@ -53,17 +55,17 @@ pub struct DecodeUtf16Error { /// ``` /// use std::char::{decode_utf16, REPLACEMENT_CHARACTER}; /// -/// fn main() { -/// // 𝄞music -/// let v = [0xD834, 0xDD1E, 0x006d, 0x0075, -/// 0x0073, 0xDD1E, 0x0069, 0x0063, -/// 0xD834]; +/// // 𝄞music +/// let v = [ +/// 0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834, +/// ]; /// -/// assert_eq!(decode_utf16(v.iter().cloned()) -/// .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)) -/// .collect::(), -/// "𝄞mus�ic�"); -/// } +/// assert_eq!( +/// decode_utf16(v.iter().cloned()) +/// .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)) +/// .collect::(), +/// "𝄞mus�ic�" +/// ); /// ``` #[stable(feature = "decode_utf16", since = "1.9.0")] #[inline] diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index aafa35873bb65..5dfdd1623061e 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -1532,12 +1532,10 @@ impl<'a> Formatter<'a> { /// } /// } /// - /// fn main() { - /// assert_eq!(&format!("{:<}", Foo), "left"); - /// assert_eq!(&format!("{:>}", Foo), "right"); - /// assert_eq!(&format!("{:^}", Foo), "center"); - /// assert_eq!(&format!("{}", Foo), "into the void"); - /// } + /// assert_eq!(&format!("{:<}", Foo), "left"); + /// assert_eq!(&format!("{:>}", Foo), "right"); + /// assert_eq!(&format!("{:^}", Foo), "center"); + /// assert_eq!(&format!("{}", Foo), "into the void"); /// ``` #[stable(feature = "fmt_flags_align", since = "1.28.0")] pub fn align(&self) -> Option { diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 933a2a124733b..83ffa8f8a842e 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -938,7 +938,9 @@ Basic usage: ``` ", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_add(1), 101); assert_eq!(", stringify!($SelfT), "::max_value().saturating_add(100), ", stringify!($SelfT), -"::max_value());", +"::max_value()); +assert_eq!(", stringify!($SelfT), "::min_value().saturating_add(-1), ", stringify!($SelfT), +"::min_value());", $EndFeature, " ```"), @@ -952,7 +954,6 @@ $EndFeature, " } } - doc_comment! { concat!("Saturating integer subtraction. Computes `self - rhs`, saturating at the numeric bounds instead of overflowing. @@ -964,7 +965,9 @@ Basic usage: ``` ", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_sub(127), -27); assert_eq!(", stringify!($SelfT), "::min_value().saturating_sub(100), ", stringify!($SelfT), -"::min_value());", +"::min_value()); +assert_eq!(", stringify!($SelfT), "::max_value().saturating_sub(-1), ", stringify!($SelfT), +"::max_value());", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index 13ccc9b252a77..933919185956e 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -2732,31 +2732,29 @@ impl Eq for *mut T {} /// impl Trait for Wrapper {} /// impl Trait for i32 {} /// -/// fn main() { -/// let wrapper = Wrapper { member: 10 }; -/// -/// // Pointers have equal addresses. -/// assert!(std::ptr::eq( -/// &wrapper as *const Wrapper as *const u8, -/// &wrapper.member as *const i32 as *const u8 -/// )); -/// -/// // Objects have equal addresses, but `Trait` has different implementations. -/// assert!(!std::ptr::eq( -/// &wrapper as &dyn Trait, -/// &wrapper.member as &dyn Trait, -/// )); -/// assert!(!std::ptr::eq( -/// &wrapper as &dyn Trait as *const dyn Trait, -/// &wrapper.member as &dyn Trait as *const dyn Trait, -/// )); -/// -/// // Converting the reference to a `*const u8` compares by address. -/// assert!(std::ptr::eq( -/// &wrapper as &dyn Trait as *const dyn Trait as *const u8, -/// &wrapper.member as &dyn Trait as *const dyn Trait as *const u8, -/// )); -/// } +/// let wrapper = Wrapper { member: 10 }; +/// +/// // Pointers have equal addresses. +/// assert!(std::ptr::eq( +/// &wrapper as *const Wrapper as *const u8, +/// &wrapper.member as *const i32 as *const u8 +/// )); +/// +/// // Objects have equal addresses, but `Trait` has different implementations. +/// assert!(!std::ptr::eq( +/// &wrapper as &dyn Trait, +/// &wrapper.member as &dyn Trait, +/// )); +/// assert!(!std::ptr::eq( +/// &wrapper as &dyn Trait as *const dyn Trait, +/// &wrapper.member as &dyn Trait as *const dyn Trait, +/// )); +/// +/// // Converting the reference to a `*const u8` compares by address. +/// assert!(std::ptr::eq( +/// &wrapper as &dyn Trait as *const dyn Trait as *const u8, +/// &wrapper.member as &dyn Trait as *const dyn Trait as *const u8, +/// )); /// ``` #[stable(feature = "ptr_eq", since = "1.17.0")] #[inline] diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index ffe1a11e81a11..87b9917f340da 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2189,44 +2189,29 @@ impl<'tcx> Borrow<[Goal<'tcx>]> for Interned<'tcx, List>> { } } -macro_rules! intern_method { - ($lt_tcx:tt, $name:ident: $method:ident($alloc:ty, - $alloc_method:expr, - $alloc_to_key:expr) -> $ty:ty) => { - impl<$lt_tcx> TyCtxt<$lt_tcx> { - pub fn $method(self, v: $alloc) -> &$lt_tcx $ty { - let key = ($alloc_to_key)(&v); - - self.interners.$name.intern_ref(key, || { - Interned($alloc_method(&self.interners.arena, v)) - - }).0 - } - } - } -} - macro_rules! direct_interners { - ($lt_tcx:tt, $($name:ident: $method:ident($ty:ty)),+) => { - $(impl<$lt_tcx> PartialEq for Interned<$lt_tcx, $ty> { + ($($name:ident: $method:ident($ty:ty)),+) => { + $(impl<'tcx> PartialEq for Interned<'tcx, $ty> { fn eq(&self, other: &Self) -> bool { self.0 == other.0 } } - impl<$lt_tcx> Eq for Interned<$lt_tcx, $ty> {} + impl<'tcx> Eq for Interned<'tcx, $ty> {} - impl<$lt_tcx> Hash for Interned<$lt_tcx, $ty> { + impl<'tcx> Hash for Interned<'tcx, $ty> { fn hash(&self, s: &mut H) { self.0.hash(s) } } - intern_method!( - $lt_tcx, - $name: $method($ty, - |a: &$lt_tcx SyncDroplessArena, v| -> &$lt_tcx $ty { a.alloc(v) }, - |x| x) -> $ty);)+ + impl<'tcx> TyCtxt<'tcx> { + pub fn $method(self, v: $ty) -> &'tcx $ty { + self.interners.$name.intern_ref(&v, || { + Interned(self.interners.arena.alloc(v)) + }).0 + } + })+ } } @@ -2234,7 +2219,7 @@ pub fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool { x.has_type_flags(ty::TypeFlags::KEEP_IN_LOCAL_TCX) } -direct_interners!('tcx, +direct_interners!( region: mk_region(RegionKind), goal: mk_goal(GoalKind<'tcx>), const_: mk_const(Const<'tcx>) @@ -2242,37 +2227,27 @@ direct_interners!('tcx, macro_rules! slice_interners { ($($field:ident: $method:ident($ty:ty)),+) => ( - $(intern_method!( 'tcx, $field: $method( - &[$ty], - |a, v| List::from_arena(a, v), - Deref::deref) -> List<$ty>);)+ + $(impl<'tcx> TyCtxt<'tcx> { + pub fn $method(self, v: &[$ty]) -> &'tcx List<$ty> { + self.interners.$field.intern_ref(v, || { + Interned(List::from_arena(&self.interners.arena, v)) + }).0 + } + })+ ); } slice_interners!( - existential_predicates: _intern_existential_predicates(ExistentialPredicate<'tcx>), - predicates: _intern_predicates(Predicate<'tcx>), type_list: _intern_type_list(Ty<'tcx>), substs: _intern_substs(GenericArg<'tcx>), + canonical_var_infos: _intern_canonical_var_infos(CanonicalVarInfo), + existential_predicates: _intern_existential_predicates(ExistentialPredicate<'tcx>), + predicates: _intern_predicates(Predicate<'tcx>), clauses: _intern_clauses(Clause<'tcx>), goal_list: _intern_goals(Goal<'tcx>), projs: _intern_projs(ProjectionKind) ); -// This isn't a perfect fit: `CanonicalVarInfo` slices are always -// allocated in the global arena, so this `intern_method!` macro is -// overly general. However, we just return `false` for the code that checks -// whether they belong in the thread-local arena, so no harm done, and -// seems better than open-coding the rest. -intern_method! { - 'tcx, - canonical_var_infos: _intern_canonical_var_infos( - &[CanonicalVarInfo], - |a, v| List::from_arena(a, v), - Deref::deref - ) -> List -} - impl<'tcx> TyCtxt<'tcx> { /// Given a `fn` type, returns an equivalent `unsafe fn` type; /// that is, a `fn` type that is equivalent in every way for being diff --git a/src/librustc_apfloat/lib.rs b/src/librustc_apfloat/lib.rs index 1190cea21acc3..5efe4fda8ccf8 100644 --- a/src/librustc_apfloat/lib.rs +++ b/src/librustc_apfloat/lib.rs @@ -555,12 +555,13 @@ pub trait Float fn ilogb(self) -> ExpInt; /// Returns: self * 2exp for integral exponents. + /// Equivalent to C standard library function `ldexp`. fn scalbn_r(self, exp: ExpInt, round: Round) -> Self; fn scalbn(self, exp: ExpInt) -> Self { self.scalbn_r(exp, Round::NearestTiesToEven) } - /// Equivalent of C standard library function. + /// Equivalent to C standard library function with the same name. /// /// While the C standard says exp is an unspecified value for infinity and nan, /// this returns INT_MAX for infinities, and INT_MIN for NaNs (see `ilogb`). diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index be5723959fb22..720d31310a13d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -128,6 +128,7 @@ use syntax::attr; use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax::source_map::{DUMMY_SP, original_sp}; use syntax::symbol::{kw, sym}; +use syntax::util::parser::ExprPrecedence; use std::cell::{Cell, RefCell, Ref, RefMut}; use std::collections::hash_map::Entry; @@ -4345,7 +4346,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let max_len = receiver.rfind(".").unwrap(); format!("{}{}", &receiver[..max_len], method_call) } else { - format!("{}{}", receiver, method_call) + if expr.precedence().order() < ExprPrecedence::MethodCall.order() { + format!("({}){}", receiver, method_call) + } else { + format!("{}{}", receiver, method_call) + } }; Some(if is_struct_pat_shorthand_field { format!("{}: {}", receiver, sugg) diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 69abbde9e6eba..ff50051ef5040 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -192,14 +192,9 @@ use crate::sys; /// ``` /// use std::collections::HashMap; /// -/// fn main() { -/// let timber_resources: HashMap<&str, i32> = -/// [("Norway", 100), -/// ("Denmark", 50), -/// ("Iceland", 10)] -/// .iter().cloned().collect(); -/// // use the values stored in map -/// } +/// let timber_resources: HashMap<&str, i32> = [("Norway", 100), ("Denmark", 50), ("Iceland", 10)] +/// .iter().cloned().collect(); +/// // use the values stored in map /// ``` #[derive(Clone)] diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 26db651ef8911..092fb44346848 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -93,11 +93,9 @@ use super::map::{self, HashMap, Keys, RandomState}; /// ``` /// use std::collections::HashSet; /// -/// fn main() { -/// let viking_names: HashSet<&'static str> = -/// [ "Einar", "Olaf", "Harald" ].iter().cloned().collect(); -/// // use the values stored in the set -/// } +/// let viking_names: HashSet<&'static str> = +/// [ "Einar", "Olaf", "Harald" ].iter().cloned().collect(); +/// // use the values stored in the set /// ``` /// /// [`Cell`]: ../../std/cell/struct.Cell.html diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index ca86a175058b5..f9255b82fc83e 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -217,11 +217,9 @@ impl SocketAddr { /// ``` /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; /// - /// fn main() { - /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); - /// assert_eq!(socket.is_ipv4(), true); - /// assert_eq!(socket.is_ipv6(), false); - /// } + /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// assert_eq!(socket.is_ipv4(), true); + /// assert_eq!(socket.is_ipv6(), false); /// ``` #[stable(feature = "sockaddr_checker", since = "1.16.0")] pub fn is_ipv4(&self) -> bool { @@ -244,12 +242,9 @@ impl SocketAddr { /// ``` /// use std::net::{IpAddr, Ipv6Addr, SocketAddr}; /// - /// fn main() { - /// let socket = SocketAddr::new( - /// IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 0, 1)), 8080); - /// assert_eq!(socket.is_ipv4(), false); - /// assert_eq!(socket.is_ipv6(), true); - /// } + /// let socket = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 0, 1)), 8080); + /// assert_eq!(socket.is_ipv4(), false); + /// assert_eq!(socket.is_ipv6(), true); /// ``` #[stable(feature = "sockaddr_checker", since = "1.16.0")] pub fn is_ipv6(&self) -> bool { diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 6b504056e5f87..70b68d1348550 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -197,11 +197,8 @@ impl IpAddr { /// /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; /// - /// fn main() { - /// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true); - /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), - /// true); - /// } + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), true); /// ``` pub fn is_global(&self) -> bool { match self { @@ -251,11 +248,11 @@ impl IpAddr { /// /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; /// - /// fn main() { - /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_documentation(), true); - /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)) - /// .is_documentation(), true); - /// } + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_documentation(), true); + /// assert_eq!( + /// IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_documentation(), + /// true + /// ); /// ``` pub fn is_documentation(&self) -> bool { match self { @@ -275,11 +272,8 @@ impl IpAddr { /// ``` /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; /// - /// fn main() { - /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true); - /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(), - /// false); - /// } + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(), false); /// ``` #[stable(feature = "ipaddr_checker", since = "1.16.0")] pub fn is_ipv4(&self) -> bool { @@ -300,11 +294,8 @@ impl IpAddr { /// ``` /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; /// - /// fn main() { - /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false); - /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(), - /// true); - /// } + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(), true); /// ``` #[stable(feature = "ipaddr_checker", since = "1.16.0")] pub fn is_ipv6(&self) -> bool { @@ -526,48 +517,46 @@ impl Ipv4Addr { /// /// use std::net::Ipv4Addr; /// - /// fn main() { - /// // private addresses are not global - /// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false); - /// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false); - /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false); + /// // private addresses are not global + /// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false); + /// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false); + /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false); /// - /// // the 0.0.0.0/8 block is not global - /// assert_eq!(Ipv4Addr::new(0, 1, 2, 3).is_global(), false); - /// // in particular, the unspecified address is not global - /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_global(), false); + /// // the 0.0.0.0/8 block is not global + /// assert_eq!(Ipv4Addr::new(0, 1, 2, 3).is_global(), false); + /// // in particular, the unspecified address is not global + /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_global(), false); /// - /// // the loopback address is not global - /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_global(), false); + /// // the loopback address is not global + /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_global(), false); /// - /// // link local addresses are not global - /// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false); + /// // link local addresses are not global + /// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false); /// - /// // the broadcast address is not global - /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_global(), false); + /// // the broadcast address is not global + /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_global(), false); /// - /// // the broadcast address is not global - /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false); - /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false); - /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false); + /// // the broadcast address is not global + /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false); + /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false); + /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false); /// - /// // shared addresses are not global - /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false); + /// // shared addresses are not global + /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false); /// - /// // addresses reserved for protocol assignment are not global - /// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_global(), false); - /// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_global(), false); + /// // addresses reserved for protocol assignment are not global + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_global(), false); + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_global(), false); /// - /// // addresses reserved for future use are not global - /// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false); + /// // addresses reserved for future use are not global + /// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false); /// - /// // addresses reserved for network devices benchmarking are not global - /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false); + /// // addresses reserved for network devices benchmarking are not global + /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false); /// - /// // All the other addresses are global - /// assert_eq!(Ipv4Addr::new(1, 1, 1, 1).is_global(), true); - /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true); - /// } + /// // All the other addresses are global + /// assert_eq!(Ipv4Addr::new(1, 1, 1, 1).is_global(), true); + /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true); /// ``` pub fn is_global(&self) -> bool { // check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two @@ -600,11 +589,9 @@ impl Ipv4Addr { /// #![feature(ip)] /// use std::net::Ipv4Addr; /// - /// fn main() { - /// assert_eq!(Ipv4Addr::new(100, 64, 0, 0).is_shared(), true); - /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true); - /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false); - /// } + /// assert_eq!(Ipv4Addr::new(100, 64, 0, 0).is_shared(), true); + /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true); + /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false); /// ``` pub fn is_shared(&self) -> bool { self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000) @@ -631,14 +618,12 @@ impl Ipv4Addr { /// #![feature(ip)] /// use std::net::Ipv4Addr; /// - /// fn main() { - /// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_ietf_protocol_assignment(), true); - /// assert_eq!(Ipv4Addr::new(192, 0, 0, 8).is_ietf_protocol_assignment(), true); - /// assert_eq!(Ipv4Addr::new(192, 0, 0, 9).is_ietf_protocol_assignment(), true); - /// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_ietf_protocol_assignment(), true); - /// assert_eq!(Ipv4Addr::new(192, 0, 1, 0).is_ietf_protocol_assignment(), false); - /// assert_eq!(Ipv4Addr::new(191, 255, 255, 255).is_ietf_protocol_assignment(), false); - /// } + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_ietf_protocol_assignment(), true); + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 8).is_ietf_protocol_assignment(), true); + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 9).is_ietf_protocol_assignment(), true); + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_ietf_protocol_assignment(), true); + /// assert_eq!(Ipv4Addr::new(192, 0, 1, 0).is_ietf_protocol_assignment(), false); + /// assert_eq!(Ipv4Addr::new(191, 255, 255, 255).is_ietf_protocol_assignment(), false); /// ``` pub fn is_ietf_protocol_assignment(&self) -> bool { self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0 @@ -658,12 +643,10 @@ impl Ipv4Addr { /// #![feature(ip)] /// use std::net::Ipv4Addr; /// - /// fn main() { - /// assert_eq!(Ipv4Addr::new(198, 17, 255, 255).is_benchmarking(), false); - /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_benchmarking(), true); - /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true); - /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false); - /// } + /// assert_eq!(Ipv4Addr::new(198, 17, 255, 255).is_benchmarking(), false); + /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_benchmarking(), true); + /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true); + /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false); /// ``` pub fn is_benchmarking(&self) -> bool { self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18 @@ -690,15 +673,12 @@ impl Ipv4Addr { /// #![feature(ip)] /// use std::net::Ipv4Addr; /// - /// fn main() { - /// assert_eq!(Ipv4Addr::new(240, 0, 0, 0).is_reserved(), true); - /// assert_eq!(Ipv4Addr::new(255, 255, 255, 254).is_reserved(), true); + /// assert_eq!(Ipv4Addr::new(240, 0, 0, 0).is_reserved(), true); + /// assert_eq!(Ipv4Addr::new(255, 255, 255, 254).is_reserved(), true); /// - /// assert_eq!(Ipv4Addr::new(239, 255, 255, 255).is_reserved(), false); - /// // The broadcast address is not considered as reserved for future use by this - /// // implementation - /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false); - /// } + /// assert_eq!(Ipv4Addr::new(239, 255, 255, 255).is_reserved(), false); + /// // The broadcast address is not considered as reserved for future use by this implementation + /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false); /// ``` pub fn is_reserved(&self) -> bool { self.octets()[0] & 240 == 240 && !self.is_broadcast() @@ -788,8 +768,10 @@ impl Ipv4Addr { /// ``` /// use std::net::{Ipv4Addr, Ipv6Addr}; /// - /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_compatible(), - /// Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 767)); + /// assert_eq!( + /// Ipv4Addr::new(192, 0, 2, 255).to_ipv6_compatible(), + /// Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 767) + /// ); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn to_ipv6_compatible(&self) -> Ipv6Addr { @@ -1161,11 +1143,9 @@ impl Ipv6Addr { /// /// use std::net::Ipv6Addr; /// - /// fn main() { - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), true); - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_global(), false); - /// assert_eq!(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1).is_global(), true); - /// } + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), true); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_global(), false); + /// assert_eq!(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1).is_global(), true); /// ``` pub fn is_global(&self) -> bool { match self.multicast_scope() { @@ -1189,11 +1169,8 @@ impl Ipv6Addr { /// /// use std::net::Ipv6Addr; /// - /// fn main() { - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), - /// false); - /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true); - /// } + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false); + /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true); /// ``` pub fn is_unique_local(&self) -> bool { (self.segments()[0] & 0xfe00) == 0xfc00 @@ -1223,21 +1200,19 @@ impl Ipv6Addr { /// /// use std::net::Ipv6Addr; /// - /// fn main() { - /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0); - /// assert!(ip.is_unicast_link_local_strict()); + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0); + /// assert!(ip.is_unicast_link_local_strict()); /// - /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff); - /// assert!(ip.is_unicast_link_local_strict()); + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff); + /// assert!(ip.is_unicast_link_local_strict()); /// - /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0); - /// assert!(!ip.is_unicast_link_local_strict()); - /// assert!(ip.is_unicast_link_local()); + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0); + /// assert!(!ip.is_unicast_link_local_strict()); + /// assert!(ip.is_unicast_link_local()); /// - /// let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0); - /// assert!(!ip.is_unicast_link_local_strict()); - /// assert!(ip.is_unicast_link_local()); - /// } + /// let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0); + /// assert!(!ip.is_unicast_link_local_strict()); + /// assert!(ip.is_unicast_link_local()); /// ``` /// /// # See also @@ -1284,21 +1259,19 @@ impl Ipv6Addr { /// /// use std::net::Ipv6Addr; /// - /// fn main() { - /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0); - /// assert!(ip.is_unicast_link_local()); + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0); + /// assert!(ip.is_unicast_link_local()); /// - /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff); - /// assert!(ip.is_unicast_link_local()); + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff); + /// assert!(ip.is_unicast_link_local()); /// - /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0); - /// assert!(ip.is_unicast_link_local()); - /// assert!(!ip.is_unicast_link_local_strict()); + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0); + /// assert!(ip.is_unicast_link_local()); + /// assert!(!ip.is_unicast_link_local_strict()); /// - /// let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0); - /// assert!(ip.is_unicast_link_local()); - /// assert!(!ip.is_unicast_link_local_strict()); - /// } + /// let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0); + /// assert!(ip.is_unicast_link_local()); + /// assert!(!ip.is_unicast_link_local_strict()); /// ``` /// /// # See also @@ -1336,11 +1309,11 @@ impl Ipv6Addr { /// /// use std::net::Ipv6Addr; /// - /// fn main() { - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_site_local(), - /// false); - /// assert_eq!(Ipv6Addr::new(0xfec2, 0, 0, 0, 0, 0, 0, 0).is_unicast_site_local(), true); - /// } + /// assert_eq!( + /// Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_site_local(), + /// false + /// ); + /// assert_eq!(Ipv6Addr::new(0xfec2, 0, 0, 0, 0, 0, 0, 0).is_unicast_site_local(), true); /// ``` /// /// # Warning @@ -1369,11 +1342,8 @@ impl Ipv6Addr { /// /// use std::net::Ipv6Addr; /// - /// fn main() { - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), - /// false); - /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true); - /// } + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false); + /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true); /// ``` pub fn is_documentation(&self) -> bool { (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8) @@ -1407,11 +1377,8 @@ impl Ipv6Addr { /// /// use std::net::Ipv6Addr; /// - /// fn main() { - /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false); - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), - /// true); - /// } + /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true); /// ``` pub fn is_unicast_global(&self) -> bool { !self.is_multicast() @@ -1431,11 +1398,11 @@ impl Ipv6Addr { /// /// use std::net::{Ipv6Addr, Ipv6MulticastScope}; /// - /// fn main() { - /// assert_eq!(Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(), - /// Some(Ipv6MulticastScope::Global)); - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None); - /// } + /// assert_eq!( + /// Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(), + /// Some(Ipv6MulticastScope::Global) + /// ); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None); /// ``` pub fn multicast_scope(&self) -> Option { if self.is_multicast() { diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index 3e389c40fbc01..a72951c034610 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -426,14 +426,12 @@ mod prim_unit { } /// /// use std::mem; /// -/// fn main() { -/// unsafe { -/// let my_num: *mut i32 = libc::malloc(mem::size_of::()) as *mut i32; -/// if my_num.is_null() { -/// panic!("failed to allocate memory"); -/// } -/// libc::free(my_num as *mut libc::c_void); +/// unsafe { +/// let my_num: *mut i32 = libc::malloc(mem::size_of::()) as *mut i32; +/// if my_num.is_null() { +/// panic!("failed to allocate memory"); /// } +/// libc::free(my_num as *mut libc::c_void); /// } /// ``` /// diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index ec5d00e0952d7..e8d7b7663ed52 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -1180,7 +1180,7 @@ impl<'a> Parser<'a> { } } - crate fn expected_semi_or_open_brace(&mut self) -> PResult<'a, ast::TraitItem> { + crate fn expected_semi_or_open_brace(&mut self) -> PResult<'a, T> { let token_str = self.this_token_descr(); let mut err = self.fatal(&format!("expected `;` or `{{`, found {}", token_str)); err.span_label(self.token.span, "expected `;` or `{`"); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 2fb6f197dad7c..95f84d5cb3314 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -511,13 +511,15 @@ impl<'a> Parser<'a> { is_present } + /// If the next token is the given keyword, returns `true` without eating it. + /// An expectation is also added for diagnostics purposes. fn check_keyword(&mut self, kw: Symbol) -> bool { self.expected_tokens.push(TokenType::Keyword(kw)); self.token.is_keyword(kw) } - /// If the next token is the given keyword, eats it and returns - /// `true`. Otherwise, returns `false`. + /// If the next token is the given keyword, eats it and returns `true`. + /// Otherwise, returns `false`. An expectation is also added for diagnostics purposes. pub fn eat_keyword(&mut self, kw: Symbol) -> bool { if self.check_keyword(kw) { self.bump(); @@ -547,40 +549,38 @@ impl<'a> Parser<'a> { } } - crate fn check_ident(&mut self) -> bool { - if self.token.is_ident() { + fn check_or_expected(&mut self, ok: bool, typ: TokenType) -> bool { + if ok { true } else { - self.expected_tokens.push(TokenType::Ident); + self.expected_tokens.push(typ); false } } + crate fn check_ident(&mut self) -> bool { + self.check_or_expected(self.token.is_ident(), TokenType::Ident) + } + fn check_path(&mut self) -> bool { - if self.token.is_path_start() { - true - } else { - self.expected_tokens.push(TokenType::Path); - false - } + self.check_or_expected(self.token.is_path_start(), TokenType::Path) } fn check_type(&mut self) -> bool { - if self.token.can_begin_type() { - true - } else { - self.expected_tokens.push(TokenType::Type); - false - } + self.check_or_expected(self.token.can_begin_type(), TokenType::Type) } fn check_const_arg(&mut self) -> bool { - if self.token.can_begin_const_arg() { - true - } else { - self.expected_tokens.push(TokenType::Const); - false - } + self.check_or_expected(self.token.can_begin_const_arg(), TokenType::Const) + } + + /// Checks to see if the next token is either `+` or `+=`. + /// Otherwise returns `false`. + fn check_plus(&mut self) -> bool { + self.check_or_expected( + self.token.is_like_plus(), + TokenType::Token(token::BinOp(token::Plus)), + ) } /// Expects and consumes a `+`. if `+=` is seen, replaces it with a `=` @@ -604,18 +604,6 @@ impl<'a> Parser<'a> { } } - /// Checks to see if the next token is either `+` or `+=`. - /// Otherwise returns `false`. - fn check_plus(&mut self) -> bool { - if self.token.is_like_plus() { - true - } - else { - self.expected_tokens.push(TokenType::Token(token::BinOp(token::Plus))); - false - } - } - /// Expects and consumes an `&`. If `&&` is seen, replaces it with a single /// `&` and continues. If an `&` is not seen, signals an error. fn expect_and(&mut self) -> PResult<'a, ()> { @@ -910,15 +898,15 @@ impl<'a> Parser<'a> { self.expected_tokens.clear(); } - pub fn look_ahead(&self, dist: usize, f: F) -> R where - F: FnOnce(&Token) -> R, - { + /// Look-ahead `dist` tokens of `self.token` and get access to that token there. + /// When `dist == 0` then the current token is looked at. + pub fn look_ahead(&self, dist: usize, looker: impl FnOnce(&Token) -> R) -> R { if dist == 0 { - return f(&self.token); + return looker(&self.token); } let frame = &self.token_cursor.frame; - f(&match frame.tree_cursor.look_ahead(dist - 1) { + looker(&match frame.tree_cursor.look_ahead(dist - 1) { Some(tree) => match tree { TokenTree::Token(token) => token, TokenTree::Delimited(dspan, delim, _) => @@ -954,109 +942,6 @@ impl<'a> Parser<'a> { } } - fn is_named_argument(&self) -> bool { - let offset = match self.token.kind { - token::Interpolated(ref nt) => match **nt { - token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon), - _ => 0, - } - token::BinOp(token::And) | token::AndAnd => 1, - _ if self.token.is_keyword(kw::Mut) => 1, - _ => 0, - }; - - self.look_ahead(offset, |t| t.is_ident()) && - self.look_ahead(offset + 1, |t| t == &token::Colon) - } - - /// Skips unexpected attributes and doc comments in this position and emits an appropriate - /// error. - /// This version of parse param doesn't necessarily require identifier names. - fn parse_param_general( - &mut self, - is_self_allowed: bool, - is_trait_item: bool, - allow_c_variadic: bool, - is_name_required: impl Fn(&token::Token) -> bool, - ) -> PResult<'a, Param> { - let lo = self.token.span; - let attrs = self.parse_outer_attributes()?; - - // Possibly parse `self`. Recover if we parsed it and it wasn't allowed here. - if let Some(mut param) = self.parse_self_param()? { - param.attrs = attrs.into(); - return if is_self_allowed { - Ok(param) - } else { - self.recover_bad_self_param(param, is_trait_item) - }; - } - - let is_name_required = is_name_required(&self.token); - let (pat, ty) = if is_name_required || self.is_named_argument() { - debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required); - - let pat = self.parse_fn_param_pat()?; - if let Err(mut err) = self.expect(&token::Colon) { - if let Some(ident) = self.parameter_without_type( - &mut err, - pat, - is_name_required, - is_trait_item, - ) { - err.emit(); - return Ok(dummy_arg(ident)); - } else { - return Err(err); - } - } - - self.eat_incorrect_doc_comment_for_param_type(); - (pat, self.parse_ty_common(true, true, allow_c_variadic)?) - } else { - debug!("parse_param_general ident_to_pat"); - let parser_snapshot_before_ty = self.clone(); - self.eat_incorrect_doc_comment_for_param_type(); - let mut ty = self.parse_ty_common(true, true, allow_c_variadic); - if ty.is_ok() && self.token != token::Comma && - self.token != token::CloseDelim(token::Paren) { - // This wasn't actually a type, but a pattern looking like a type, - // so we are going to rollback and re-parse for recovery. - ty = self.unexpected(); - } - match ty { - Ok(ty) => { - let ident = Ident::new(kw::Invalid, self.prev_span); - let bm = BindingMode::ByValue(Mutability::Immutable); - let pat = self.mk_pat_ident(ty.span, bm, ident); - (pat, ty) - } - Err(mut err) => { - // If this is a C-variadic argument and we hit an error, return the - // error. - if self.token == token::DotDotDot { - return Err(err); - } - // Recover from attempting to parse the argument as a type without pattern. - err.cancel(); - mem::replace(self, parser_snapshot_before_ty); - self.recover_arg_parse()? - } - } - }; - - let span = lo.to(self.token.span); - - Ok(Param { - attrs: attrs.into(), - id: ast::DUMMY_NODE_ID, - is_placeholder: false, - pat, - span, - ty, - }) - } - /// Parses mutability (`mut` or nothing). fn parse_mutability(&mut self) -> Mutability { if self.eat_keyword(kw::Mut) { @@ -1066,6 +951,17 @@ impl<'a> Parser<'a> { } } + /// Possibly parses mutability (`const` or `mut`). + fn parse_const_or_mut(&mut self) -> Option { + if self.eat_keyword(kw::Mut) { + Some(Mutability::Mutable) + } else if self.eat_keyword(kw::Const) { + Some(Mutability::Immutable) + } else { + None + } + } + fn parse_field_name(&mut self) -> PResult<'a, Ident> { if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) = self.token.kind { @@ -1100,9 +996,10 @@ impl<'a> Parser<'a> { Ok((delim, tts.into())) } - fn parse_or_use_outer_attributes(&mut self, - already_parsed_attrs: Option>) - -> PResult<'a, ThinVec> { + fn parse_or_use_outer_attributes( + &mut self, + already_parsed_attrs: Option>, + ) -> PResult<'a, ThinVec> { if let Some(attrs) = already_parsed_attrs { Ok(attrs) } else { @@ -1189,53 +1086,52 @@ impl<'a> Parser<'a> { /// Evaluates the closure with restrictions in place. /// /// Afters the closure is evaluated, restrictions are reset. - fn with_res(&mut self, r: Restrictions, f: F) -> T - where F: FnOnce(&mut Self) -> T - { + fn with_res(&mut self, res: Restrictions, f: impl FnOnce(&mut Self) -> T) -> T { let old = self.restrictions; - self.restrictions = r; - let r = f(self); + self.restrictions = res; + let res = f(self); self.restrictions = old; - return r; - + res } - fn parse_fn_params(&mut self, named_params: bool, allow_c_variadic: bool) - -> PResult<'a, Vec> { + fn parse_fn_params( + &mut self, + named_params: bool, + allow_c_variadic: bool, + ) -> PResult<'a, Vec> { let sp = self.token.span; + let do_not_enforce_named_params_for_c_variadic = |token: &token::Token| { + match token.kind { + token::DotDotDot => false, + _ => named_params, + } + }; let mut c_variadic = false; - let (params, _): (Vec>, _) = self.parse_paren_comma_seq(|p| { - let do_not_enforce_named_arguments_for_c_variadic = - |token: &token::Token| -> bool { - if token == &token::DotDotDot { - false - } else { - named_params - } - }; + let (params, _) = self.parse_paren_comma_seq(|p| { match p.parse_param_general( false, false, allow_c_variadic, - do_not_enforce_named_arguments_for_c_variadic + do_not_enforce_named_params_for_c_variadic, ) { - Ok(param) => { + Ok(param) => Ok( if let TyKind::CVarArgs = param.ty.kind { c_variadic = true; if p.token != token::CloseDelim(token::Paren) { - let span = p.token.span; - p.span_err(span, - "`...` must be the last argument of a C-variadic function"); + p.span_err( + p.token.span, + "`...` must be the last argument of a C-variadic function", + ); // FIXME(eddyb) this should probably still push `CVarArgs`. // Maybe AST validation/HIR lowering should emit the above error? - Ok(None) + None } else { - Ok(Some(param)) + Some(param) } } else { - Ok(Some(param)) + Some(param) } - }, + ), Err(mut e) => { e.emit(); let lo = p.prev_span; @@ -1251,26 +1147,169 @@ impl<'a> Parser<'a> { let params: Vec<_> = params.into_iter().filter_map(|x| x).collect(); if c_variadic && params.len() <= 1 { - self.span_err(sp, - "C-variadic function must be declared with at least one named argument"); + self.span_err( + sp, + "C-variadic function must be declared with at least one named argument", + ); } Ok(params) } + /// Parses the parameter list and result type of a function that may have a `self` parameter. + fn parse_fn_decl_with_self( + &mut self, + is_name_required: impl Copy + Fn(&token::Token) -> bool, + ) -> PResult<'a, P> { + // Parse the arguments, starting out with `self` being allowed... + let mut is_self_allowed = true; + let (mut inputs, _): (Vec<_>, _) = self.parse_paren_comma_seq(|p| { + let res = p.parse_param_general(is_self_allowed, true, false, is_name_required); + // ...but now that we've parsed the first argument, `self` is no longer allowed. + is_self_allowed = false; + res + })?; + + // Replace duplicated recovered params with `_` pattern to avoid unecessary errors. + self.deduplicate_recovered_params_names(&mut inputs); + + Ok(P(FnDecl { + inputs, + output: self.parse_ret_ty(true)?, + })) + } + + /// Skips unexpected attributes and doc comments in this position and emits an appropriate + /// error. + /// This version of parse param doesn't necessarily require identifier names. + fn parse_param_general( + &mut self, + is_self_allowed: bool, + is_trait_item: bool, + allow_c_variadic: bool, + is_name_required: impl Fn(&token::Token) -> bool, + ) -> PResult<'a, Param> { + let lo = self.token.span; + let attrs = self.parse_outer_attributes()?; + + // Possibly parse `self`. Recover if we parsed it and it wasn't allowed here. + if let Some(mut param) = self.parse_self_param()? { + param.attrs = attrs.into(); + return if is_self_allowed { + Ok(param) + } else { + self.recover_bad_self_param(param, is_trait_item) + }; + } + + let is_name_required = is_name_required(&self.token); + let (pat, ty) = if is_name_required || self.is_named_param() { + debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required); + + let pat = self.parse_fn_param_pat()?; + if let Err(mut err) = self.expect(&token::Colon) { + if let Some(ident) = self.parameter_without_type( + &mut err, + pat, + is_name_required, + is_trait_item, + ) { + err.emit(); + return Ok(dummy_arg(ident)); + } else { + return Err(err); + } + } + + self.eat_incorrect_doc_comment_for_param_type(); + (pat, self.parse_ty_common(true, true, allow_c_variadic)?) + } else { + debug!("parse_param_general ident_to_pat"); + let parser_snapshot_before_ty = self.clone(); + self.eat_incorrect_doc_comment_for_param_type(); + let mut ty = self.parse_ty_common(true, true, allow_c_variadic); + if ty.is_ok() && self.token != token::Comma && + self.token != token::CloseDelim(token::Paren) { + // This wasn't actually a type, but a pattern looking like a type, + // so we are going to rollback and re-parse for recovery. + ty = self.unexpected(); + } + match ty { + Ok(ty) => { + let ident = Ident::new(kw::Invalid, self.prev_span); + let bm = BindingMode::ByValue(Mutability::Immutable); + let pat = self.mk_pat_ident(ty.span, bm, ident); + (pat, ty) + } + // If this is a C-variadic argument and we hit an error, return the error. + Err(err) if self.token == token::DotDotDot => return Err(err), + // Recover from attempting to parse the argument as a type without pattern. + Err(mut err) => { + err.cancel(); + mem::replace(self, parser_snapshot_before_ty); + self.recover_arg_parse()? + } + } + }; + + let span = lo.to(self.token.span); + + Ok(Param { + attrs: attrs.into(), + id: ast::DUMMY_NODE_ID, + is_placeholder: false, + pat, + span, + ty, + }) + } + /// Returns the parsed optional self parameter and whether a self shortcut was used. /// /// See `parse_self_param_with_attrs` to collect attributes. fn parse_self_param(&mut self) -> PResult<'a, Option> { - let expect_ident = |this: &mut Self| match this.token.kind { - // Preserve hygienic context. - token::Ident(name, _) => - { let span = this.token.span; this.bump(); Ident::new(name, span) } - _ => unreachable!() + // Extract an identifier *after* having confirmed that the token is one. + let expect_self_ident = |this: &mut Self| { + match this.token.kind { + // Preserve hygienic context. + token::Ident(name, _) => { + let span = this.token.span; + this.bump(); + Ident::new(name, span) + } + _ => unreachable!(), + } + }; + // Is `self` `n` tokens ahead? + let is_isolated_self = |this: &Self, n| { + this.is_keyword_ahead(n, &[kw::SelfLower]) + && this.look_ahead(n + 1, |t| t != &token::ModSep) }; - let isolated_self = |this: &mut Self, n| { - this.look_ahead(n, |t| t.is_keyword(kw::SelfLower)) && - this.look_ahead(n + 1, |t| t != &token::ModSep) + // Is `mut self` `n` tokens ahead? + let is_isolated_mut_self = |this: &Self, n| { + this.is_keyword_ahead(n, &[kw::Mut]) + && is_isolated_self(this, n + 1) + }; + // Parse `self` or `self: TYPE`. We already know the current token is `self`. + let parse_self_possibly_typed = |this: &mut Self, m| { + let eself_ident = expect_self_ident(this); + let eself_hi = this.prev_span; + let eself = if this.eat(&token::Colon) { + SelfKind::Explicit(this.parse_ty()?, m) + } else { + SelfKind::Value(m) + }; + Ok((eself, eself_ident, eself_hi)) + }; + // Recover for the grammar `*self`, `*const self`, and `*mut self`. + let recover_self_ptr = |this: &mut Self| { + let msg = "cannot pass `self` by raw pointer"; + let span = this.token.span; + this.struct_span_err(span, msg) + .span_label(span, msg) + .emit(); + + Ok((SelfKind::Value(Mutability::Immutable), expect_self_ident(this), this.prev_span)) }; // Parse optional `self` parameter of a method. @@ -1279,88 +1318,54 @@ impl<'a> Parser<'a> { let eself_lo = self.token.span; let (eself, eself_ident, eself_hi) = match self.token.kind { token::BinOp(token::And) => { - // `&self` - // `&mut self` - // `&'lt self` - // `&'lt mut self` - // `¬_self` - (if isolated_self(self, 1) { + let eself = if is_isolated_self(self, 1) { + // `&self` self.bump(); SelfKind::Region(None, Mutability::Immutable) - } else if self.is_keyword_ahead(1, &[kw::Mut]) && - isolated_self(self, 2) { + } else if is_isolated_mut_self(self, 1) { + // `&mut self` self.bump(); self.bump(); SelfKind::Region(None, Mutability::Mutable) - } else if self.look_ahead(1, |t| t.is_lifetime()) && - isolated_self(self, 2) { + } else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_self(self, 2) { + // `&'lt self` self.bump(); let lt = self.expect_lifetime(); SelfKind::Region(Some(lt), Mutability::Immutable) - } else if self.look_ahead(1, |t| t.is_lifetime()) && - self.is_keyword_ahead(2, &[kw::Mut]) && - isolated_self(self, 3) { + } else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_mut_self(self, 2) { + // `&'lt mut self` self.bump(); let lt = self.expect_lifetime(); self.bump(); SelfKind::Region(Some(lt), Mutability::Mutable) } else { + // `¬_self` return Ok(None); - }, expect_ident(self), self.prev_span) + }; + (eself, expect_self_ident(self), self.prev_span) } - token::BinOp(token::Star) => { - // `*self` - // `*const self` - // `*mut self` - // `*not_self` - // Emit special error for `self` cases. - let msg = "cannot pass `self` by raw pointer"; - (if isolated_self(self, 1) { - self.bump(); - self.struct_span_err(self.token.span, msg) - .span_label(self.token.span, msg) - .emit(); - SelfKind::Value(Mutability::Immutable) - } else if self.look_ahead(1, |t| t.is_mutability()) && - isolated_self(self, 2) { - self.bump(); - self.bump(); - self.struct_span_err(self.token.span, msg) - .span_label(self.token.span, msg) - .emit(); - SelfKind::Value(Mutability::Immutable) - } else { - return Ok(None); - }, expect_ident(self), self.prev_span) + // `*self` + token::BinOp(token::Star) if is_isolated_self(self, 1) => { + self.bump(); + recover_self_ptr(self)? } - token::Ident(..) => { - if isolated_self(self, 0) { - // `self` - // `self: TYPE` - let eself_ident = expect_ident(self); - let eself_hi = self.prev_span; - (if self.eat(&token::Colon) { - let ty = self.parse_ty()?; - SelfKind::Explicit(ty, Mutability::Immutable) - } else { - SelfKind::Value(Mutability::Immutable) - }, eself_ident, eself_hi) - } else if self.token.is_keyword(kw::Mut) && - isolated_self(self, 1) { - // `mut self` - // `mut self: TYPE` - self.bump(); - let eself_ident = expect_ident(self); - let eself_hi = self.prev_span; - (if self.eat(&token::Colon) { - let ty = self.parse_ty()?; - SelfKind::Explicit(ty, Mutability::Mutable) - } else { - SelfKind::Value(Mutability::Mutable) - }, eself_ident, eself_hi) - } else { - return Ok(None); - } + // `*mut self` and `*const self` + token::BinOp(token::Star) if + self.look_ahead(1, |t| t.is_mutability()) + && is_isolated_self(self, 2) => + { + self.bump(); + self.bump(); + recover_self_ptr(self)? + } + // `self` and `self: TYPE` + token::Ident(..) if is_isolated_self(self, 0) => { + parse_self_possibly_typed(self, Mutability::Immutable)? + } + // `mut self` and `mut self: TYPE` + token::Ident(..) if is_isolated_mut_self(self, 0) => { + self.bump(); + parse_self_possibly_typed(self, Mutability::Mutable)? } _ => return Ok(None), }; @@ -1369,27 +1374,19 @@ impl<'a> Parser<'a> { Ok(Some(Param::from_self(ThinVec::default(), eself, eself_ident))) } - /// Parses the parameter list and result type of a function that may have a `self` parameter. - fn parse_fn_decl_with_self( - &mut self, - is_name_required: impl Copy + Fn(&token::Token) -> bool, - ) -> PResult<'a, P> { - // Parse the arguments, starting out with `self` being allowed... - let mut is_self_allowed = true; - let (mut inputs, _): (Vec<_>, _) = self.parse_paren_comma_seq(|p| { - let res = p.parse_param_general(is_self_allowed, true, false, is_name_required); - // ...but now that we've parsed the first argument, `self` is no longer allowed. - is_self_allowed = false; - res - })?; - - // Replace duplicated recovered params with `_` pattern to avoid unecessary errors. - self.deduplicate_recovered_params_names(&mut inputs); + fn is_named_param(&self) -> bool { + let offset = match self.token.kind { + token::Interpolated(ref nt) => match **nt { + token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon), + _ => 0, + } + token::BinOp(token::And) | token::AndAnd => 1, + _ if self.token.is_keyword(kw::Mut) => 1, + _ => 0, + }; - Ok(P(FnDecl { - inputs, - output: self.parse_ret_ty(true)?, - })) + self.look_ahead(offset, |t| t.is_ident()) && + self.look_ahead(offset + 1, |t| t == &token::Colon) } fn is_crate_vis(&self) -> bool { @@ -1423,100 +1420,107 @@ impl<'a> Parser<'a> { // `()` or a tuple might be allowed. For example, `struct Struct(pub (), pub (usize));`. // Because of this, we only `bump` the `(` if we're assured it is appropriate to do so // by the following tokens. - if self.is_keyword_ahead(1, &[kw::Crate]) && - self.look_ahead(2, |t| t != &token::ModSep) // account for `pub(crate::foo)` + if self.is_keyword_ahead(1, &[kw::Crate]) + && self.look_ahead(2, |t| t != &token::ModSep) // account for `pub(crate::foo)` { - // `pub(crate)` + // Parse `pub(crate)`. self.bump(); // `(` self.bump(); // `crate` self.expect(&token::CloseDelim(token::Paren))?; // `)` - let vis = respan( - lo.to(self.prev_span), - VisibilityKind::Crate(CrateSugar::PubCrate), - ); - return Ok(vis) + let vis = VisibilityKind::Crate(CrateSugar::PubCrate); + return Ok(respan(lo.to(self.prev_span), vis)); } else if self.is_keyword_ahead(1, &[kw::In]) { - // `pub(in path)` + // Parse `pub(in path)`. self.bump(); // `(` self.bump(); // `in` let path = self.parse_path(PathStyle::Mod)?; // `path` self.expect(&token::CloseDelim(token::Paren))?; // `)` - let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted { + let vis = VisibilityKind::Restricted { path: P(path), id: ast::DUMMY_NODE_ID, - }); - return Ok(vis) - } else if self.look_ahead(2, |t| t == &token::CloseDelim(token::Paren)) && - self.is_keyword_ahead(1, &[kw::Super, kw::SelfLower]) + }; + return Ok(respan(lo.to(self.prev_span), vis)); + } else if self.look_ahead(2, |t| t == &token::CloseDelim(token::Paren)) + && self.is_keyword_ahead(1, &[kw::Super, kw::SelfLower]) { - // `pub(self)` or `pub(super)` + // Parse `pub(self)` or `pub(super)`. self.bump(); // `(` let path = self.parse_path(PathStyle::Mod)?; // `super`/`self` self.expect(&token::CloseDelim(token::Paren))?; // `)` - let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted { + let vis = VisibilityKind::Restricted { path: P(path), id: ast::DUMMY_NODE_ID, - }); - return Ok(vis) - } else if !can_take_tuple { // Provide this diagnostic if this is not a tuple struct - // `pub(something) fn ...` or `struct X { pub(something) y: Z }` - self.bump(); // `(` - let msg = "incorrect visibility restriction"; - let suggestion = r##"some possible visibility restrictions are: -`pub(crate)`: visible only on the current crate -`pub(super)`: visible only in the current module's parent -`pub(in path::to::module)`: visible only on the specified path"##; - let path = self.parse_path(PathStyle::Mod)?; - let sp = path.span; - let help_msg = format!("make this visible only to module `{}` with `in`", path); - self.expect(&token::CloseDelim(token::Paren))?; // `)` - struct_span_err!(self.sess.span_diagnostic, sp, E0704, "{}", msg) - .help(suggestion) - .span_suggestion( - sp, - &help_msg, - format!("in {}", path), - Applicability::MachineApplicable, - ) - .emit(); // Emit diagnostic, but continue with public visibility. + }; + return Ok(respan(lo.to(self.prev_span), vis)); + } else if !can_take_tuple { // Provide this diagnostic if this is not a tuple struct. + self.recover_incorrect_vis_restriction()?; + // Emit diagnostic, but continue with public visibility. } } Ok(respan(lo, VisibilityKind::Public)) } + /// Recovery for e.g. `pub(something) fn ...` or `struct X { pub(something) y: Z }` + fn recover_incorrect_vis_restriction(&mut self) -> PResult<'a, ()> { + self.bump(); // `(` + let path = self.parse_path(PathStyle::Mod)?; + self.expect(&token::CloseDelim(token::Paren))?; // `)` + + let msg = "incorrect visibility restriction"; + let suggestion = r##"some possible visibility restrictions are: +`pub(crate)`: visible only on the current crate +`pub(super)`: visible only in the current module's parent +`pub(in path::to::module)`: visible only on the specified path"##; + + struct_span_err!(self.sess.span_diagnostic, path.span, E0704, "{}", msg) + .help(suggestion) + .span_suggestion( + path.span, + &format!("make this visible only to module `{}` with `in`", path), + format!("in {}", path), + Applicability::MachineApplicable, + ) + .emit(); + + Ok(()) + } + /// Parses a string as an ABI spec on an extern type or module. Consumes /// the `extern` keyword, if one is found. fn parse_opt_abi(&mut self) -> PResult<'a, Option> { match self.token.kind { token::Literal(token::Lit { kind: token::Str, symbol, suffix }) | token::Literal(token::Lit { kind: token::StrRaw(..), symbol, suffix }) => { - let sp = self.token.span; - self.expect_no_suffix(sp, "an ABI spec", suffix); + self.expect_no_suffix(self.token.span, "an ABI spec", suffix); self.bump(); match abi::lookup(&symbol.as_str()) { Some(abi) => Ok(Some(abi)), None => { - let prev_span = self.prev_span; - struct_span_err!( - self.sess.span_diagnostic, - prev_span, - E0703, - "invalid ABI: found `{}`", - symbol - ) - .span_label(prev_span, "invalid ABI") - .help(&format!("valid ABIs: {}", abi::all_names().join(", "))) - .emit(); + self.error_on_invalid_abi(symbol); Ok(None) } } } - _ => Ok(None), } } + /// Emit an error where `symbol` is an invalid ABI. + fn error_on_invalid_abi(&self, symbol: Symbol) { + let prev_span = self.prev_span; + struct_span_err!( + self.sess.span_diagnostic, + prev_span, + E0703, + "invalid ABI: found `{}`", + symbol + ) + .span_label(prev_span, "invalid ABI") + .help(&format!("valid ABIs: {}", abi::all_names().join(", "))) + .emit(); + } + /// We are parsing `async fn`. If we are on Rust 2015, emit an error. fn ban_async_in_2015(&self, async_span: Span) { if async_span.rust_2015() { @@ -1530,9 +1534,10 @@ impl<'a> Parser<'a> { } } - fn collect_tokens(&mut self, f: F) -> PResult<'a, (R, TokenStream)> - where F: FnOnce(&mut Self) -> PResult<'a, R> - { + fn collect_tokens( + &mut self, + f: impl FnOnce(&mut Self) -> PResult<'a, R>, + ) -> PResult<'a, (R, TokenStream)> { // Record all tokens we parse when parsing this item. let mut tokens = Vec::new(); let prev_collecting = match self.token_cursor.frame.last_token { diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index 64c494416ff34..c00a5807d52c5 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -7,7 +7,7 @@ use crate::ast::{ Item, ItemKind, ImplItem, TraitItem, TraitItemKind, UseTree, UseTreeKind, PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, - Visibility, VisibilityKind, Mutability, FnDecl, FnHeader, + Visibility, VisibilityKind, Mutability, FnDecl, FnHeader, MethodSig, Block, ForeignItem, ForeignItemKind, Ty, TyKind, Generics, GenericBounds, TraitRef, EnumDef, VariantData, StructField, AnonConst, @@ -18,7 +18,7 @@ use crate::parse::token; use crate::parse::parser::maybe_append; use crate::parse::diagnostics::Error; use crate::tokenstream::{TokenTree, TokenStream}; -use crate::source_map::{respan, Span, Spanned}; +use crate::source_map::{respan, Span}; use crate::symbol::{kw, sym}; use std::mem; @@ -122,19 +122,13 @@ impl<'a> Parser<'a> { if self.eat_keyword(kw::Fn) { // EXTERN FUNCTION ITEM let fn_span = self.prev_span; - let abi = opt_abi.unwrap_or(Abi::C); - let (ident, item_, extra_attrs) = - self.parse_item_fn(Unsafety::Normal, - respan(fn_span, IsAsync::NotAsync), - respan(fn_span, Constness::NotConst), - abi)?; - let prev_span = self.prev_span; - let item = self.mk_item(lo.to(prev_span), - ident, - item_, - visibility, - maybe_append(attrs, extra_attrs)); - return Ok(Some(item)); + let header = FnHeader { + unsafety: Unsafety::Normal, + asyncness: respan(fn_span, IsAsync::NotAsync), + constness: respan(fn_span, Constness::NotConst), + abi: opt_abi.unwrap_or(Abi::C), + }; + return self.parse_item_fn(lo, visibility, attrs, header); } else if self.check(&token::OpenDelim(token::Brace)) { return Ok(Some( self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs, extern_sp)?, @@ -149,13 +143,9 @@ impl<'a> Parser<'a> { // STATIC ITEM let m = self.parse_mutability(); let (ident, item_, extra_attrs) = self.parse_item_const(Some(m))?; - let prev_span = self.prev_span; - let item = self.mk_item(lo.to(prev_span), - ident, - item_, - visibility, - maybe_append(attrs, extra_attrs)); - return Ok(Some(item)); + let span = lo.to(self.prev_span); + let attrs = maybe_append(attrs, extra_attrs); + return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs))); } if self.eat_keyword(kw::Const) { let const_span = self.prev_span; @@ -165,18 +155,13 @@ impl<'a> Parser<'a> { // CONST FUNCTION ITEM let unsafety = self.parse_unsafety(); self.bump(); - let (ident, item_, extra_attrs) = - self.parse_item_fn(unsafety, - respan(const_span, IsAsync::NotAsync), - respan(const_span, Constness::Const), - Abi::Rust)?; - let prev_span = self.prev_span; - let item = self.mk_item(lo.to(prev_span), - ident, - item_, - visibility, - maybe_append(attrs, extra_attrs)); - return Ok(Some(item)); + let header = FnHeader { + unsafety, + asyncness: respan(const_span, IsAsync::NotAsync), + constness: respan(const_span, Constness::Const), + abi: Abi::Rust, + }; + return self.parse_item_fn(lo, visibility, attrs, header); } // CONST ITEM @@ -193,13 +178,9 @@ impl<'a> Parser<'a> { .emit(); } let (ident, item_, extra_attrs) = self.parse_item_const(None)?; - let prev_span = self.prev_span; - let item = self.mk_item(lo.to(prev_span), - ident, - item_, - visibility, - maybe_append(attrs, extra_attrs)); - return Ok(Some(item)); + let span = lo.to(self.prev_span); + let attrs = maybe_append(attrs, extra_attrs); + return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs))); } // Parses `async unsafe? fn`. @@ -213,22 +194,18 @@ impl<'a> Parser<'a> { let unsafety = self.parse_unsafety(); // `unsafe`? self.expect_keyword(kw::Fn)?; // `fn` let fn_span = self.prev_span; - let (ident, item_, extra_attrs) = - self.parse_item_fn(unsafety, - respan(async_span, IsAsync::Async { - closure_id: DUMMY_NODE_ID, - return_impl_trait_id: DUMMY_NODE_ID, - }), - respan(fn_span, Constness::NotConst), - Abi::Rust)?; - let prev_span = self.prev_span; - let item = self.mk_item(lo.to(prev_span), - ident, - item_, - visibility, - maybe_append(attrs, extra_attrs)); + let asyncness = respan(async_span, IsAsync::Async { + closure_id: DUMMY_NODE_ID, + return_impl_trait_id: DUMMY_NODE_ID, + }); self.ban_async_in_2015(async_span); - return Ok(Some(item)); + let header = FnHeader { + unsafety, + asyncness, + constness: respan(fn_span, Constness::NotConst), + abi: Abi::Rust, + }; + return self.parse_item_fn(lo, visibility, attrs, header); } } if self.check_keyword(kw::Unsafe) && @@ -243,15 +220,10 @@ impl<'a> Parser<'a> { self.expect_keyword(kw::Trait)?; IsAuto::Yes }; - let (ident, item_, extra_attrs) = - self.parse_item_trait(is_auto, Unsafety::Unsafe)?; - let prev_span = self.prev_span; - let item = self.mk_item(lo.to(prev_span), - ident, - item_, - visibility, - maybe_append(attrs, extra_attrs)); - return Ok(Some(item)); + let (ident, item_, extra_attrs) = self.parse_item_trait(is_auto, Unsafety::Unsafe)?; + let span = lo.to(self.prev_span); + let attrs = maybe_append(attrs, extra_attrs); + return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs))); } if self.check_keyword(kw::Impl) || self.check_keyword(kw::Unsafe) && @@ -262,27 +234,22 @@ impl<'a> Parser<'a> { let defaultness = self.parse_defaultness(); let unsafety = self.parse_unsafety(); self.expect_keyword(kw::Impl)?; - let (ident, item, extra_attrs) = self.parse_item_impl(unsafety, defaultness)?; + let (ident, item_, extra_attrs) = self.parse_item_impl(unsafety, defaultness)?; let span = lo.to(self.prev_span); - return Ok(Some(self.mk_item(span, ident, item, visibility, - maybe_append(attrs, extra_attrs)))); + let attrs = maybe_append(attrs, extra_attrs); + return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs))); } if self.check_keyword(kw::Fn) { // FUNCTION ITEM self.bump(); let fn_span = self.prev_span; - let (ident, item_, extra_attrs) = - self.parse_item_fn(Unsafety::Normal, - respan(fn_span, IsAsync::NotAsync), - respan(fn_span, Constness::NotConst), - Abi::Rust)?; - let prev_span = self.prev_span; - let item = self.mk_item(lo.to(prev_span), - ident, - item_, - visibility, - maybe_append(attrs, extra_attrs)); - return Ok(Some(item)); + let header = FnHeader { + unsafety: Unsafety::Normal, + asyncness: respan(fn_span, IsAsync::NotAsync), + constness: respan(fn_span, Constness::NotConst), + abi: Abi::Rust, + }; + return self.parse_item_fn(lo, visibility, attrs, header); } if self.check_keyword(kw::Unsafe) && self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) { @@ -297,30 +264,20 @@ impl<'a> Parser<'a> { }; self.expect_keyword(kw::Fn)?; let fn_span = self.prev_span; - let (ident, item_, extra_attrs) = - self.parse_item_fn(Unsafety::Unsafe, - respan(fn_span, IsAsync::NotAsync), - respan(fn_span, Constness::NotConst), - abi)?; - let prev_span = self.prev_span; - let item = self.mk_item(lo.to(prev_span), - ident, - item_, - visibility, - maybe_append(attrs, extra_attrs)); - return Ok(Some(item)); + let header = FnHeader { + unsafety: Unsafety::Unsafe, + asyncness: respan(fn_span, IsAsync::NotAsync), + constness: respan(fn_span, Constness::NotConst), + abi, + }; + return self.parse_item_fn(lo, visibility, attrs, header); } if self.eat_keyword(kw::Mod) { // MODULE ITEM - let (ident, item_, extra_attrs) = - self.parse_item_mod(&attrs[..])?; - let prev_span = self.prev_span; - let item = self.mk_item(lo.to(prev_span), - ident, - item_, - visibility, - maybe_append(attrs, extra_attrs)); - return Ok(Some(item)); + let (ident, item_, extra_attrs) = self.parse_item_mod(&attrs[..])?; + let span = lo.to(self.prev_span); + let attrs = maybe_append(attrs, extra_attrs); + return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs))); } if let Some(type_) = self.eat_type() { let (ident, alias, generics) = type_?; @@ -329,24 +286,15 @@ impl<'a> Parser<'a> { AliasKind::Weak(ty) => ItemKind::TyAlias(ty, generics), AliasKind::OpaqueTy(bounds) => ItemKind::OpaqueTy(bounds, generics), }; - let prev_span = self.prev_span; - let item = self.mk_item(lo.to(prev_span), - ident, - item_, - visibility, - attrs); - return Ok(Some(item)); + let span = lo.to(self.prev_span); + return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs))); } if self.eat_keyword(kw::Enum) { // ENUM ITEM let (ident, item_, extra_attrs) = self.parse_item_enum()?; - let prev_span = self.prev_span; - let item = self.mk_item(lo.to(prev_span), - ident, - item_, - visibility, - maybe_append(attrs, extra_attrs)); - return Ok(Some(item)); + let span = lo.to(self.prev_span); + let attrs = maybe_append(attrs, extra_attrs); + return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs))); } if self.check_keyword(kw::Trait) || (self.check_keyword(kw::Auto) @@ -360,38 +308,25 @@ impl<'a> Parser<'a> { IsAuto::Yes }; // TRAIT ITEM - let (ident, item_, extra_attrs) = - self.parse_item_trait(is_auto, Unsafety::Normal)?; - let prev_span = self.prev_span; - let item = self.mk_item(lo.to(prev_span), - ident, - item_, - visibility, - maybe_append(attrs, extra_attrs)); - return Ok(Some(item)); + let (ident, item_, extra_attrs) = self.parse_item_trait(is_auto, Unsafety::Normal)?; + let span = lo.to(self.prev_span); + let attrs = maybe_append(attrs, extra_attrs); + return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs))); } if self.eat_keyword(kw::Struct) { // STRUCT ITEM let (ident, item_, extra_attrs) = self.parse_item_struct()?; - let prev_span = self.prev_span; - let item = self.mk_item(lo.to(prev_span), - ident, - item_, - visibility, - maybe_append(attrs, extra_attrs)); - return Ok(Some(item)); + let span = lo.to(self.prev_span); + let attrs = maybe_append(attrs, extra_attrs); + return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs))); } if self.is_union_item() { // UNION ITEM self.bump(); let (ident, item_, extra_attrs) = self.parse_item_union()?; - let prev_span = self.prev_span; - let item = self.mk_item(lo.to(prev_span), - ident, - item_, - visibility, - maybe_append(attrs, extra_attrs)); - return Ok(Some(item)); + let span = lo.to(self.prev_span); + let attrs = maybe_append(attrs, extra_attrs); + return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs))); } if let Some(macro_def) = self.eat_macro_def(&attrs, &visibility, lo)? { return Ok(Some(macro_def)); @@ -848,29 +783,37 @@ impl<'a> Parser<'a> { } /// Parses a method or a macro invocation in a trait impl. - fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool) - -> PResult<'a, (Ident, Vec, Generics, ast::ImplItemKind)> { + fn parse_impl_method( + &mut self, + vis: &Visibility, + at_end: &mut bool + ) -> PResult<'a, (Ident, Vec, Generics, ast::ImplItemKind)> { // FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction! if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(vis), at_end)? { // method macro - Ok((Ident::invalid(), vec![], Generics::default(), - ast::ImplItemKind::Macro(mac))) + Ok((Ident::invalid(), vec![], Generics::default(), ast::ImplItemKind::Macro(mac))) } else { - let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?; - let ident = self.parse_ident()?; - let mut generics = self.parse_generics()?; - let decl = self.parse_fn_decl_with_self(|_| true)?; - generics.where_clause = self.parse_where_clause()?; + let (ident, sig, generics) = self.parse_method_sig(|_| true)?; *at_end = true; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - let header = ast::FnHeader { abi, unsafety, constness, asyncness }; - Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method( - ast::MethodSig { header, decl }, - body - ))) + Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(sig, body))) } } + /// Parse the "signature", including the identifier, parameters, and generics + /// of a method. The body is not parsed as that differs between `trait`s and `impl`s. + fn parse_method_sig( + &mut self, + is_name_required: impl Copy + Fn(&token::Token) -> bool, + ) -> PResult<'a, (Ident, MethodSig, Generics)> { + let header = self.parse_fn_front_matter()?; + let (ident, mut generics) = self.parse_fn_header()?; + let decl = self.parse_fn_decl_with_self(is_name_required)?; + let sig = MethodSig { header, decl }; + generics.where_clause = self.parse_where_clause()?; + Ok((ident, sig, generics)) + } + /// Parses all the "front matter" for a `fn` declaration, up to /// and including the `fn` keyword: /// @@ -879,14 +822,7 @@ impl<'a> Parser<'a> { /// - `const unsafe fn` /// - `extern fn` /// - etc. - fn parse_fn_front_matter(&mut self) - -> PResult<'a, ( - Spanned, - Unsafety, - Spanned, - Abi - )> - { + fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> { let is_const_fn = self.eat_keyword(kw::Const); let const_span = self.prev_span; let asyncness = self.parse_asyncness(); @@ -911,7 +847,7 @@ impl<'a> Parser<'a> { // account for this. if !self.expect_one_of(&[], &[])? { unreachable!() } } - Ok((constness, unsafety, asyncness, abi)) + Ok(FnHeader { constness, unsafety, asyncness, abi }) } /// Parses `trait Foo { ... }` or `trait Foo = Bar;`. @@ -1025,59 +961,12 @@ impl<'a> Parser<'a> { // trait item macro. (Ident::invalid(), ast::TraitItemKind::Macro(mac), Generics::default()) } else { - let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?; - - let ident = self.parse_ident()?; - let mut generics = self.parse_generics()?; - // This is somewhat dubious; We don't want to allow // argument names to be left off if there is a definition... // // We don't allow argument names to be left off in edition 2018. - let decl = self.parse_fn_decl_with_self(|t| t.span.rust_2018())?; - generics.where_clause = self.parse_where_clause()?; - - let sig = ast::MethodSig { - header: FnHeader { - unsafety, - constness, - abi, - asyncness, - }, - decl, - }; - - let body = match self.token.kind { - token::Semi => { - self.bump(); - *at_end = true; - debug!("parse_trait_methods(): parsing required method"); - None - } - token::OpenDelim(token::Brace) => { - debug!("parse_trait_methods(): parsing provided method"); - *at_end = true; - let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - attrs.extend(inner_attrs.iter().cloned()); - Some(body) - } - token::Interpolated(ref nt) => { - match **nt { - token::NtBlock(..) => { - *at_end = true; - let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - attrs.extend(inner_attrs.iter().cloned()); - Some(body) - } - _ => { - return self.expected_semi_or_open_brace(); - } - } - } - _ => { - return self.expected_semi_or_open_brace(); - } - }; + let (ident, sig, generics) = self.parse_method_sig(|t| t.span.rust_2018())?; + let body = self.parse_trait_method_body(at_end, &mut attrs)?; (ident, ast::TraitItemKind::Method(sig, body), generics) }; @@ -1092,6 +981,43 @@ impl<'a> Parser<'a> { }) } + /// Parse the "body" of a method in a trait item definition. + /// This can either be `;` when there's no body, + /// or e.g. a block when the method is a provided one. + fn parse_trait_method_body( + &mut self, + at_end: &mut bool, + attrs: &mut Vec, + ) -> PResult<'a, Option>> { + Ok(match self.token.kind { + token::Semi => { + debug!("parse_trait_method_body(): parsing required method"); + self.bump(); + *at_end = true; + None + } + token::OpenDelim(token::Brace) => { + debug!("parse_trait_method_body(): parsing provided method"); + *at_end = true; + let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; + attrs.extend(inner_attrs.iter().cloned()); + Some(body) + } + token::Interpolated(ref nt) => { + match **nt { + token::NtBlock(..) => { + *at_end = true; + let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; + attrs.extend(inner_attrs.iter().cloned()); + Some(body) + } + _ => return self.expected_semi_or_open_brace(), + } + } + _ => return self.expected_semi_or_open_brace(), + }) + } + /// Parses the following grammar: /// /// TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] @@ -1261,18 +1187,29 @@ impl<'a> Parser<'a> { /// Parses an item-position function declaration. fn parse_item_fn( &mut self, - unsafety: Unsafety, - asyncness: Spanned, - constness: Spanned, - abi: Abi - ) -> PResult<'a, ItemInfo> { + lo: Span, + vis: Visibility, + attrs: Vec, + header: FnHeader, + ) -> PResult<'a, Option>> { + let allow_c_variadic = header.abi == Abi::C && header.unsafety == Unsafety::Unsafe; + let (ident, decl, generics) = self.parse_fn_sig(allow_c_variadic)?; + let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; + let span = lo.to(self.prev_span); + let kind = ItemKind::Fn(decl, header, generics, body); + let attrs = maybe_append(attrs, Some(inner_attrs)); + Ok(Some(self.mk_item(span, ident, kind, vis, attrs))) + } + + /// Parse the "signature", including the identifier, parameters, and generics of a function. + fn parse_fn_sig( + &mut self, + allow_c_variadic: bool, + ) -> PResult<'a, (Ident, P, Generics)> { let (ident, mut generics) = self.parse_fn_header()?; - let allow_c_variadic = abi == Abi::C && unsafety == Unsafety::Unsafe; let decl = self.parse_fn_decl(allow_c_variadic)?; generics.where_clause = self.parse_where_clause()?; - let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - let header = FnHeader { unsafety, asyncness, constness, abi }; - Ok((ident, ItemKind::Fn(decl, header, generics, body), Some(inner_attrs))) + Ok((ident, decl, generics)) } /// Parses the name and optional generic types of a function header. @@ -1282,14 +1219,11 @@ impl<'a> Parser<'a> { Ok((id, generics)) } - /// Parses the argument list and result type of a function declaration. + /// Parses the parameter list and result type of a function declaration. fn parse_fn_decl(&mut self, allow_c_variadic: bool) -> PResult<'a, P> { - let args = self.parse_fn_params(true, allow_c_variadic)?; - let ret_ty = self.parse_ret_ty(true)?; - Ok(P(FnDecl { - inputs: args, - output: ret_ty, + inputs: self.parse_fn_params(true, allow_c_variadic)?, + output: self.parse_ret_ty(true)?, })) } @@ -1397,18 +1331,15 @@ impl<'a> Parser<'a> { extern_sp: Span, ) -> PResult<'a, ForeignItem> { self.expect_keyword(kw::Fn)?; - - let (ident, mut generics) = self.parse_fn_header()?; - let decl = self.parse_fn_decl(true)?; - generics.where_clause = self.parse_where_clause()?; - let hi = self.token.span; + let (ident, decl, generics) = self.parse_fn_sig(true)?; + let span = lo.to(self.token.span); self.parse_semi_or_incorrect_foreign_fn_body(&ident, extern_sp)?; Ok(ast::ForeignItem { ident, attrs, kind: ForeignItemKind::Fn(decl, generics), id: DUMMY_NODE_ID, - span: lo.to(hi), + span, vis, }) } diff --git a/src/libsyntax/parse/parser/ty.rs b/src/libsyntax/parse/parser/ty.rs index c52d3733b5e0a..41ee2a1599d74 100644 --- a/src/libsyntax/parse/parser/ty.rs +++ b/src/libsyntax/parse/parser/ty.rs @@ -231,11 +231,7 @@ impl<'a> Parser<'a> { } fn parse_ptr(&mut self) -> PResult<'a, MutTy> { - let mutbl = if self.eat_keyword(kw::Mut) { - Mutability::Mutable - } else if self.eat_keyword(kw::Const) { - Mutability::Immutable - } else { + let mutbl = self.parse_const_or_mut().unwrap_or_else(|| { let span = self.prev_span; let msg = "expected mut or const in raw pointer type"; self.struct_span_err(span, msg) @@ -243,7 +239,7 @@ impl<'a> Parser<'a> { .help("use `*mut T` or `*const T` as appropriate") .emit(); Mutability::Immutable - }; + }); let t = self.parse_ty_no_plus()?; Ok(MutTy { ty: t, mutbl }) } diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr index d3f88af09d134..7633825eb32ab 100644 --- a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr +++ b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr @@ -10,18 +10,18 @@ error[E0670]: `async fn` is not permitted in the 2015 edition LL | fn baz() { async fn foo() {} } | ^^^^^ -error[E0670]: `async fn` is not permitted in the 2015 edition - --> $DIR/edition-deny-async-fns-2015.rs:8:5 - | -LL | async fn bar() {} - | ^^^^^ - error[E0670]: `async fn` is not permitted in the 2015 edition --> $DIR/edition-deny-async-fns-2015.rs:7:1 | LL | async fn async_baz() { | ^^^^^ +error[E0670]: `async fn` is not permitted in the 2015 edition + --> $DIR/edition-deny-async-fns-2015.rs:8:5 + | +LL | async fn bar() {} + | ^^^^^ + error[E0670]: `async fn` is not permitted in the 2015 edition --> $DIR/edition-deny-async-fns-2015.rs:14:5 | diff --git a/src/test/ui/conversion-methods.stderr b/src/test/ui/conversion-methods.stderr index b9662e7607494..5c666afb89a33 100644 --- a/src/test/ui/conversion-methods.stderr +++ b/src/test/ui/conversion-methods.stderr @@ -41,7 +41,7 @@ LL | let _prove_piercing_earnest: Vec = &[1, 2, 3]; | ^^^^^^^^^^ | | | expected struct `std::vec::Vec`, found reference - | help: try using a conversion method: `&[1, 2, 3].to_vec()` + | help: try using a conversion method: `(&[1, 2, 3]).to_vec()` | = note: expected type `std::vec::Vec` found type `&[{integer}; 3]` diff --git a/src/test/ui/infinite/infinite-autoderef.stderr b/src/test/ui/infinite/infinite-autoderef.stderr index a2ad58a7e46fc..f4567554d0dbb 100644 --- a/src/test/ui/infinite/infinite-autoderef.stderr +++ b/src/test/ui/infinite/infinite-autoderef.stderr @@ -5,7 +5,7 @@ LL | x = box x; | ^^^^^ | | | cyclic type of infinite size - | help: try using a conversion method: `box x.to_string()` + | help: try using a conversion method: `(box x).to_string()` error[E0055]: reached the recursion limit while auto-dereferencing `Foo` --> $DIR/infinite-autoderef.rs:25:5 diff --git a/src/test/ui/mismatched_types/abridged.rs b/src/test/ui/mismatched_types/abridged.rs index 41ab6d4c57844..9a5c183ca3428 100644 --- a/src/test/ui/mismatched_types/abridged.rs +++ b/src/test/ui/mismatched_types/abridged.rs @@ -50,4 +50,13 @@ fn e() -> X, String> { x //~ ERROR mismatched types } +fn f() -> String { + 1+2 //~ ERROR mismatched types +} + + +fn g() -> String { + -2 //~ ERROR mismatched types +} + fn main() {} diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr index b7f3b3dde8a93..ded12d89c099d 100644 --- a/src/test/ui/mismatched_types/abridged.stderr +++ b/src/test/ui/mismatched_types/abridged.stderr @@ -66,6 +66,34 @@ LL | x = note: expected type `X, _>` found type `X, _>` -error: aborting due to 6 previous errors +error[E0308]: mismatched types + --> $DIR/abridged.rs:54:5 + | +LL | fn f() -> String { + | ------ expected `std::string::String` because of return type +LL | 1+2 + | ^^^ + | | + | expected struct `std::string::String`, found integer + | help: try using a conversion method: `(1+2).to_string()` + | + = note: expected type `std::string::String` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/abridged.rs:59:5 + | +LL | fn g() -> String { + | ------ expected `std::string::String` because of return type +LL | -2 + | ^^ + | | + | expected struct `std::string::String`, found integer + | help: try using a conversion method: `(-2).to_string()` + | + = note: expected type `std::string::String` + found type `{integer}` + +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/occurs-check-2.stderr b/src/test/ui/occurs-check-2.stderr index 74e29a5aea728..7f93697c6f7a7 100644 --- a/src/test/ui/occurs-check-2.stderr +++ b/src/test/ui/occurs-check-2.stderr @@ -5,7 +5,7 @@ LL | f = box g; | ^^^^^ | | | cyclic type of infinite size - | help: try using a conversion method: `box g.to_string()` + | help: try using a conversion method: `(box g).to_string()` error: aborting due to previous error diff --git a/src/test/ui/occurs-check.stderr b/src/test/ui/occurs-check.stderr index 61ce61b1cbeb6..01e2b1f774910 100644 --- a/src/test/ui/occurs-check.stderr +++ b/src/test/ui/occurs-check.stderr @@ -5,7 +5,7 @@ LL | f = box f; | ^^^^^ | | | cyclic type of infinite size - | help: try using a conversion method: `box f.to_string()` + | help: try using a conversion method: `(box f).to_string()` error: aborting due to previous error diff --git a/src/test/ui/span/coerce-suggestions.stderr b/src/test/ui/span/coerce-suggestions.stderr index 996d80a07e058..0d15a2a753ed0 100644 --- a/src/test/ui/span/coerce-suggestions.stderr +++ b/src/test/ui/span/coerce-suggestions.stderr @@ -44,7 +44,7 @@ LL | f = box f; | ^^^^^ | | | cyclic type of infinite size - | help: try using a conversion method: `box f.to_string()` + | help: try using a conversion method: `(box f).to_string()` error[E0308]: mismatched types --> $DIR/coerce-suggestions.rs:21:9