Auto merge of #64972 - Centril:rollup-gcawast, r=Centril
Rollup of 7 pull requests Successful merges: - #63416 (apfloat: improve doc comments) - #64820 (BTreeSet intersection, is_subset & difference optimizations) - #64910 (syntax: cleanup param, method, and misc parsing) - #64912 (Remove unneeded `fn main` blocks from docs) - #64933 (Fixes #64919. Suggest fix based on operator precendence.) - #64943 (Add lower bound doctests for `saturating_{add,sub}` signed ints) - #64950 (Simplify interners) Failed merges: r? @ghost
This commit is contained in:
commit
7130fc54e0
36 changed files with 1108 additions and 1107 deletions
|
@ -29,10 +29,8 @@
|
|||
//! Nil,
|
||||
//! }
|
||||
//!
|
||||
//! fn main() {
|
||||
//! let list: List<i32> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil))));
|
||||
//! println!("{:?}", list);
|
||||
//! }
|
||||
//! let list: List<i32> = 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<T: ?Sized> Box<T> {
|
|||
/// ```
|
||||
/// #![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<T: ?Sized> Box<T> {
|
|||
/// 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<dyn Any> {
|
|||
/// }
|
||||
/// }
|
||||
///
|
||||
/// 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<T: Any>(self) -> Result<Box<T>, Box<dyn Any>> {
|
||||
if self.is::<T>() {
|
||||
|
@ -814,11 +804,9 @@ impl Box<dyn Any + Send> {
|
|||
/// }
|
||||
/// }
|
||||
///
|
||||
/// 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<T: Any>(self) -> Result<Box<T>, Box<dyn Any + Send>> {
|
||||
<Box<dyn Any>>::downcast(self).map_err(|s| unsafe {
|
||||
|
|
|
@ -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<usize>> = BTreeMap::new();
|
||||
/// map.entry("poneyland").or_default();
|
||||
///
|
||||
/// assert_eq!(map["poneyland"], None);
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn or_default(self) -> &'a mut V {
|
||||
match self {
|
||||
|
|
|
@ -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<Iter<'a, T>>,
|
||||
},
|
||||
Search {
|
||||
// iterate a small set, look up in the large set
|
||||
self_iter: Iter<'a, T>,
|
||||
other_set: &'a BTreeSet<T>,
|
||||
},
|
||||
Iterate(Iter<'a, T>), // simply stream self's elements
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
|
@ -147,6 +150,7 @@ impl<T: fmt::Debug> 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<T>,
|
||||
},
|
||||
Answer(Option<&'a T>), // return a specific value or emptiness
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
|
@ -212,6 +219,9 @@ impl<T: fmt::Debug> 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<T: Ord> BTreeSet<T> {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn difference<'a>(&'a self, other: &'a BTreeSet<T>) -> 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<T: Ord> BTreeSet<T> {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn intersection<'a>(&'a self, other: &'a BTreeSet<T>) -> 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<T: Ord> BTreeSet<T> {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn is_subset(&self, other: &BTreeSet<T>) -> 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 a1 = a.unwrap();
|
||||
let b1 = b.unwrap();
|
||||
|
||||
match b1.cmp(a1) {
|
||||
Less => (),
|
||||
Greater => return false,
|
||||
Equal => a = x.next(),
|
||||
}
|
||||
|
||||
b = y.next();
|
||||
}
|
||||
true
|
||||
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 {
|
||||
// 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 {
|
||||
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;
|
||||
}
|
||||
}
|
||||
true
|
||||
} else {
|
||||
// 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
|
||||
}
|
||||
|
||||
/// Returns `true` if the set is a superset of another,
|
||||
|
@ -1120,6 +1194,7 @@ impl<T> 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<T> 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<usize>) {
|
||||
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)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -861,11 +861,9 @@ impl Rc<dyn Any> {
|
|||
/// }
|
||||
/// }
|
||||
///
|
||||
/// 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<T: Any>(self) -> Result<Rc<T>, Rc<dyn Any>> {
|
||||
if (*self).is::<T>() {
|
||||
|
|
|
@ -412,20 +412,15 @@ impl<T> [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?",
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -164,10 +164,8 @@ use crate::vec::Vec;
|
|||
///
|
||||
/// fn example_func<A: TraitExample>(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
|
||||
|
|
|
@ -1244,11 +1244,9 @@ impl Arc<dyn Any + Send + Sync> {
|
|||
/// }
|
||||
/// }
|
||||
///
|
||||
/// 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<T>(self) -> Result<Arc<T>, Self>
|
||||
where
|
||||
|
|
|
@ -48,7 +48,9 @@ fn check<F>(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::<Vec<_>>();
|
||||
let large = (0..100).collect::<Vec<_>>();
|
||||
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<i32> = [3, 4].iter().copied().collect();
|
||||
let y: BTreeSet<i32> = [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::<Vec<_>>();
|
||||
let large = (0..100).collect::<Vec<_>>();
|
||||
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<i32> = [2, 4, 6].iter().copied().collect();
|
||||
let s23456: BTreeSet<i32> = (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<i32> = (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<i32> = (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<i32> = (-9..=1).collect();
|
||||
iter = s246.difference(&s1);
|
||||
assert_eq!(iter.size_hint(), (3, Some(3)));
|
||||
|
||||
let s2: BTreeSet<i32> = (-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<i32> = (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<i32> = (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<i32> = (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<i32> = (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<i32> = (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::<Vec<_>>();
|
||||
let large = (0..100).collect::<Vec<_>>();
|
||||
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]
|
||||
|
|
|
@ -389,28 +389,26 @@ impl<T> Vec<T> {
|
|||
/// use std::ptr;
|
||||
/// use std::mem;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let mut v = vec![1, 2, 3];
|
||||
/// 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();
|
||||
/// // Pull out the various important pieces of information about `v`
|
||||
/// let p = v.as_mut_ptr();
|
||||
/// let len = v.len();
|
||||
/// let cap = v.capacity();
|
||||
///
|
||||
/// 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);
|
||||
/// 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);
|
||||
///
|
||||
/// // 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]);
|
||||
/// // 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<T> Vec<T> {
|
|||
/// ```
|
||||
/// #![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]
|
||||
|
|
|
@ -87,10 +87,8 @@ pub trait Any: 'static {
|
|||
/// TypeId::of::<String>() == 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::<String>() == TypeId::of::<T>()
|
||||
/// }
|
||||
///
|
||||
/// 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")]
|
||||
|
|
|
@ -111,11 +111,9 @@ impl From<char> 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<u8> 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 {
|
||||
|
|
|
@ -31,21 +31,23 @@ pub struct DecodeUtf16Error {
|
|||
/// ```
|
||||
/// use std::char::decode_utf16;
|
||||
///
|
||||
/// fn main() {
|
||||
/// // 𝄞mus<invalid>ic<invalid>
|
||||
/// let v = [0xD834, 0xDD1E, 0x006d, 0x0075,
|
||||
/// 0x0073, 0xDD1E, 0x0069, 0x0063,
|
||||
/// 0xD834];
|
||||
/// // 𝄞mus<invalid>ic<invalid>
|
||||
/// 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<_>>(),
|
||||
/// 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<_>>(),
|
||||
/// 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() {
|
||||
/// // 𝄞mus<invalid>ic<invalid>
|
||||
/// let v = [0xD834, 0xDD1E, 0x006d, 0x0075,
|
||||
/// 0x0073, 0xDD1E, 0x0069, 0x0063,
|
||||
/// 0xD834];
|
||||
/// // 𝄞mus<invalid>ic<invalid>
|
||||
/// 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::<String>(),
|
||||
/// "𝄞mus<75>ic<69>");
|
||||
/// }
|
||||
/// assert_eq!(
|
||||
/// decode_utf16(v.iter().cloned())
|
||||
/// .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
|
||||
/// .collect::<String>(),
|
||||
/// "𝄞mus<75>ic<69>"
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "decode_utf16", since = "1.9.0")]
|
||||
#[inline]
|
||||
|
|
|
@ -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<Alignment> {
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -2732,31 +2732,29 @@ impl<T: ?Sized> Eq for *mut T {}
|
|||
/// impl Trait for Wrapper {}
|
||||
/// impl Trait for i32 {}
|
||||
///
|
||||
/// fn main() {
|
||||
/// let wrapper = Wrapper { member: 10 };
|
||||
/// 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
|
||||
/// ));
|
||||
/// // 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,
|
||||
/// ));
|
||||
/// // 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,
|
||||
/// ));
|
||||
/// }
|
||||
/// // 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]
|
||||
|
|
|
@ -2189,44 +2189,29 @@ impl<'tcx> Borrow<[Goal<'tcx>]> for Interned<'tcx, List<Goal<'tcx>>> {
|
|||
}
|
||||
}
|
||||
|
||||
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<H: Hasher>(&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<CanonicalVarInfo>
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -555,12 +555,13 @@ pub trait Float
|
|||
fn ilogb(self) -> ExpInt;
|
||||
|
||||
/// Returns: self * 2<sup>exp</sup> 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`).
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<Ipv6MulticastScope> {
|
||||
if self.is_multicast() {
|
||||
|
|
|
@ -426,14 +426,12 @@ mod prim_unit { }
|
|||
///
|
||||
/// use std::mem;
|
||||
///
|
||||
/// fn main() {
|
||||
/// unsafe {
|
||||
/// let my_num: *mut i32 = libc::malloc(mem::size_of::<i32>()) 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::<i32>()) as *mut i32;
|
||||
/// if my_num.is_null() {
|
||||
/// panic!("failed to allocate memory");
|
||||
/// }
|
||||
/// libc::free(my_num as *mut libc::c_void);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
|
|
|
@ -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<T>(&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 `{`");
|
||||
|
|
|
@ -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<R, F>(&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<R>(&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<Mutability> {
|
||||
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<ThinVec<Attribute>>)
|
||||
-> PResult<'a, ThinVec<Attribute>> {
|
||||
fn parse_or_use_outer_attributes(
|
||||
&mut self,
|
||||
already_parsed_attrs: Option<ThinVec<Attribute>>,
|
||||
) -> PResult<'a, ThinVec<Attribute>> {
|
||||
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<F, T>(&mut self, r: Restrictions, f: F) -> T
|
||||
where F: FnOnce(&mut Self) -> T
|
||||
{
|
||||
fn with_res<T>(&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<Param>> {
|
||||
fn parse_fn_params(
|
||||
&mut self,
|
||||
named_params: bool,
|
||||
allow_c_variadic: bool,
|
||||
) -> PResult<'a, Vec<Param>> {
|
||||
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<Option<Param>>, _) = 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,124 +1147,15 @@ 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)
|
||||
}
|
||||
|
||||
/// 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<Param>> {
|
||||
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!()
|
||||
};
|
||||
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)
|
||||
};
|
||||
|
||||
// Parse optional `self` parameter of a method.
|
||||
// Only a limited set of initial token sequences is considered `self` parameters; anything
|
||||
// else is parsed as a normal function parameter list, so some lookahead is required.
|
||||
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) {
|
||||
self.bump();
|
||||
SelfKind::Region(None, Mutability::Immutable)
|
||||
} else if self.is_keyword_ahead(1, &[kw::Mut]) &&
|
||||
isolated_self(self, 2) {
|
||||
self.bump();
|
||||
self.bump();
|
||||
SelfKind::Region(None, Mutability::Mutable)
|
||||
} else if self.look_ahead(1, |t| t.is_lifetime()) &&
|
||||
isolated_self(self, 2) {
|
||||
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) {
|
||||
self.bump();
|
||||
let lt = self.expect_lifetime();
|
||||
self.bump();
|
||||
SelfKind::Region(Some(lt), Mutability::Mutable)
|
||||
} else {
|
||||
return Ok(None);
|
||||
}, expect_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)
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
_ => return Ok(None),
|
||||
};
|
||||
|
||||
let eself = source_map::respan(eself_lo.to(eself_hi), eself);
|
||||
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,
|
||||
|
@ -1392,6 +1179,216 @@ impl<'a> Parser<'a> {
|
|||
}))
|
||||
}
|
||||
|
||||
/// 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<Param>> {
|
||||
// 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)
|
||||
};
|
||||
// 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.
|
||||
// Only a limited set of initial token sequences is considered `self` parameters; anything
|
||||
// else is parsed as a normal function parameter list, so some lookahead is required.
|
||||
let eself_lo = self.token.span;
|
||||
let (eself, eself_ident, eself_hi) = match self.token.kind {
|
||||
token::BinOp(token::And) => {
|
||||
let eself = if is_isolated_self(self, 1) {
|
||||
// `&self`
|
||||
self.bump();
|
||||
SelfKind::Region(None, Mutability::Immutable)
|
||||
} 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()) && 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()) && 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);
|
||||
};
|
||||
(eself, expect_self_ident(self), self.prev_span)
|
||||
}
|
||||
// `*self`
|
||||
token::BinOp(token::Star) if is_isolated_self(self, 1) => {
|
||||
self.bump();
|
||||
recover_self_ptr(self)?
|
||||
}
|
||||
// `*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),
|
||||
};
|
||||
|
||||
let eself = source_map::respan(eself_lo.to(eself_hi), eself);
|
||||
Ok(Some(Param::from_self(ThinVec::default(), eself, eself_ident)))
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
self.look_ahead(offset, |t| t.is_ident()) &&
|
||||
self.look_ahead(offset + 1, |t| t == &token::Colon)
|
||||
}
|
||||
|
||||
fn is_crate_vis(&self) -> bool {
|
||||
self.token.is_keyword(kw::Crate) && self.look_ahead(1, |t| t != &token::ModSep)
|
||||
}
|
||||
|
@ -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<Abi>> {
|
||||
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<F, R>(&mut self, f: F) -> PResult<'a, (R, TokenStream)>
|
||||
where F: FnOnce(&mut Self) -> PResult<'a, R>
|
||||
{
|
||||
fn collect_tokens<R>(
|
||||
&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 {
|
||||
|
|
|
@ -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<Attribute>, Generics, ast::ImplItemKind)> {
|
||||
fn parse_impl_method(
|
||||
&mut self,
|
||||
vis: &Visibility,
|
||||
at_end: &mut bool
|
||||
) -> PResult<'a, (Ident, Vec<Attribute>, 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<Constness>,
|
||||
Unsafety,
|
||||
Spanned<IsAsync>,
|
||||
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<Attribute>,
|
||||
) -> PResult<'a, Option<P<Block>>> {
|
||||
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<IsAsync>,
|
||||
constness: Spanned<Constness>,
|
||||
abi: Abi
|
||||
) -> PResult<'a, ItemInfo> {
|
||||
lo: Span,
|
||||
vis: Visibility,
|
||||
attrs: Vec<Attribute>,
|
||||
header: FnHeader,
|
||||
) -> PResult<'a, Option<P<Item>>> {
|
||||
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<FnDecl>, 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<FnDecl>> {
|
||||
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,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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 })
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
||||
|
|
|
@ -41,7 +41,7 @@ LL | let _prove_piercing_earnest: Vec<usize> = &[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<usize>`
|
||||
found type `&[{integer}; 3]`
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -50,4 +50,13 @@ fn e() -> X<X<String, String>, String> {
|
|||
x //~ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn f() -> String {
|
||||
1+2 //~ ERROR mismatched types
|
||||
}
|
||||
|
||||
|
||||
fn g() -> String {
|
||||
-2 //~ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -66,6 +66,34 @@ LL | x
|
|||
= note: expected type `X<X<_, std::string::String>, _>`
|
||||
found type `X<X<_, {integer}>, _>`
|
||||
|
||||
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`.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue