From 44ca3da9a386665834e34d27e30ed471253f2777 Mon Sep 17 00:00:00 2001 From: Nathan West Date: Wed, 20 May 2020 21:10:02 -0400 Subject: [PATCH 1/9] Various minor improvements to Ipv6Addr::Display - Defer to Ipv4Addr::fmt when printing an Ipv4 address - Fast path: write directly to f without an intermediary buffer when there are no alignment options - Simplify finding the inner zeroes-span --- src/libstd/net/ip.rs | 158 +++++++++++++++++++++---------------------- 1 file changed, 78 insertions(+), 80 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index edc28033c9b83..d50230a8859a1 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -7,9 +7,9 @@ )] use crate::cmp::Ordering; -use crate::fmt; +use crate::fmt::{self, Write as FmtWrite}; use crate::hash; -use crate::io::Write; +use crate::io::Write as IoWrite; use crate::sys::net::netc as c; use crate::sys_common::{AsInner, FromInner}; @@ -1525,102 +1525,100 @@ impl Ipv6Addr { } } +/// Write an Ipv6Addr, conforming to the canonical style described by +/// [RFC 5952](https://tools.ietf.org/html/rfc5952). #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for Ipv6Addr { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - // Note: The calls to write should never fail, hence the unwraps in the function - // Long enough for the longest possible IPv6: 39 - const IPV6_BUF_LEN: usize = 39; - let mut buf = [0u8; IPV6_BUF_LEN]; - let mut buf_slice = &mut buf[..]; + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // If there are no alignment requirements, write out the IP address to + // f. Otherwise, write it to a local buffer, then use f.pad. + if f.precision().is_none() && f.width().is_none() { + let segments = self.segments(); + + // Special case for :: and ::1; otherwise they get written with the + // IPv4 formatter + if self.is_unspecified() { + f.write_str("::") + } else if self.is_loopback() { + f.write_str("::1") + } else if let Some(ipv4) = self.to_ipv4() { + match segments[5] { + // IPv4 Compatible address + 0 => write!(f, "::{}", ipv4), + // IPv4 Mapped address + 0xffff => write!(f, "::ffff:{}", ipv4), + _ => unreachable!(), + } + } else { + #[derive(Copy, Clone, Default)] + struct Span { + start: usize, + len: usize, + } - match self.segments() { - // We need special cases for :: and ::1, otherwise they're formatted - // as ::0.0.0.[01] - [0, 0, 0, 0, 0, 0, 0, 0] => write!(buf_slice, "::").unwrap(), - [0, 0, 0, 0, 0, 0, 0, 1] => write!(buf_slice, "::1").unwrap(), - // Ipv4 Compatible address - [0, 0, 0, 0, 0, 0, g, h] => { - write!( - buf_slice, - "::{}.{}.{}.{}", - (g >> 8) as u8, - g as u8, - (h >> 8) as u8, - h as u8 - ) - .unwrap(); - } - // Ipv4-Mapped address - [0, 0, 0, 0, 0, 0xffff, g, h] => { - write!( - buf_slice, - "::ffff:{}.{}.{}.{}", - (g >> 8) as u8, - g as u8, - (h >> 8) as u8, - h as u8 - ) - .unwrap(); - } - _ => { - fn find_zero_slice(segments: &[u16; 8]) -> (usize, usize) { - let mut longest_span_len = 0; - let mut longest_span_at = 0; - let mut cur_span_len = 0; - let mut cur_span_at = 0; - - for i in 0..8 { - if segments[i] == 0 { - if cur_span_len == 0 { - cur_span_at = i; + // Find the inner 0 span + let zeroes = { + let mut longest = Span::default(); + let mut current = Span::default(); + + for (i, &segment) in segments.iter().enumerate() { + if segment == 0 { + if current.len == 0 { + current.start = i; } - cur_span_len += 1; + current.len += 1; - if cur_span_len > longest_span_len { - longest_span_len = cur_span_len; - longest_span_at = cur_span_at; + if current.len > longest.len { + longest = current; } } else { - cur_span_len = 0; - cur_span_at = 0; + current = Span::default(); } } - (longest_span_at, longest_span_len) - } - - let (zeros_at, zeros_len) = find_zero_slice(&self.segments()); - - if zeros_len > 1 { - fn fmt_subslice(segments: &[u16], buf: &mut &mut [u8]) { - if !segments.is_empty() { - write!(*buf, "{:x}", segments[0]).unwrap(); - for &seg in &segments[1..] { - write!(*buf, ":{:x}", seg).unwrap(); - } + longest + }; + + /// Write a colon-separated part of the address + #[inline] + fn fmt_subslice(f: &mut fmt::Formatter<'_>, chunk: &[u16]) -> fmt::Result { + if let Some(first) = chunk.first() { + fmt::LowerHex::fmt(first, f)?; + for segment in &chunk[1..] { + f.write_char(':')?; + fmt::LowerHex::fmt(segment, f)?; } } + Ok(()) + } - fmt_subslice(&self.segments()[..zeros_at], &mut buf_slice); - write!(buf_slice, "::").unwrap(); - fmt_subslice(&self.segments()[zeros_at + zeros_len..], &mut buf_slice); + if zeroes.len > 1 { + fmt_subslice(f, &segments[..zeroes.start])?; + f.write_str("::")?; + fmt_subslice(f, &segments[zeroes.start + zeroes.len..]) } else { - let &[a, b, c, d, e, f, g, h] = &self.segments(); - write!( - buf_slice, - "{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}", - a, b, c, d, e, f, g, h - ) - .unwrap(); + fmt_subslice(f, &segments) } } + } else { + // Slow path: write the address to a local buffer, the use f.pad. + // Defined recursively by using the fast path to write to the + // buffer. + + // This is the largest possible size of an IPv6 address + const IPV6_BUF_LEN: usize = (4 * 8) + 7; + let mut buf = [0u8; IPV6_BUF_LEN]; + let mut buf_slice = &mut buf[..]; + + // Note: This call to write should never fail, so unwrap is okay. + write!(buf_slice, "{}", self).unwrap(); + let len = IPV6_BUF_LEN - buf_slice.len(); + + // This is safe because we know exactly what can be in this buffer + let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) }; + f.pad(buf) } - let len = IPV6_BUF_LEN - buf_slice.len(); - // This is safe because we know exactly what can be in this buffer - let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) }; - fmt.pad(buf) } } From 4e2696f54a449a366d2dae23bbc737947ec529ce Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Mon, 25 May 2020 15:53:41 -0400 Subject: [PATCH 2/9] Only capture tokens for items with outer attributes Suggested by @petrochenkov in https://github.com/rust-lang/rust/issues/43081#issuecomment-633389225 --- src/librustc_parse/parser/item.rs | 21 ++++++++++++++----- .../ast-json/ast-json-noexpand-output.stdout | 2 +- src/test/ui/ast-json/ast-json-output.stdout | 2 +- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 4fe0453e9c87f..6f13d7994d17d 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -106,11 +106,20 @@ impl<'a> Parser<'a> { }); let mut unclosed_delims = vec![]; - let (mut item, tokens) = self.collect_tokens(|this| { + let has_attrs = !attrs.is_empty(); + let parse_item = |this: &mut Self| { let item = this.parse_item_common_(attrs, mac_allowed, attrs_allowed, req_name); unclosed_delims.append(&mut this.unclosed_delims); item - })?; + }; + + let (mut item, tokens) = if has_attrs { + let (item, tokens) = self.collect_tokens(parse_item)?; + (item, Some(tokens)) + } else { + (parse_item(self)?, None) + }; + self.unclosed_delims.append(&mut unclosed_delims); // Once we've parsed an item and recorded the tokens we got while @@ -127,9 +136,11 @@ impl<'a> Parser<'a> { // it (bad!). To work around this case for now we just avoid recording // `tokens` if we detect any inner attributes. This should help keep // expansion correct, but we should fix this bug one day! - if let Some(item) = &mut item { - if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) { - item.tokens = Some(tokens); + if let Some(tokens) = tokens { + if let Some(item) = &mut item { + if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) { + item.tokens = Some(tokens); + } } } Ok(item) diff --git a/src/test/ui/ast-json/ast-json-noexpand-output.stdout b/src/test/ui/ast-json/ast-json-noexpand-output.stdout index f60b6a00be129..c7b0fbeb0e39b 100644 --- a/src/test/ui/ast-json/ast-json-noexpand-output.stdout +++ b/src/test/ui/ast-json/ast-json-noexpand-output.stdout @@ -1 +1 @@ -{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"NonJoint"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]} +{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"NonJoint"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]} diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout index 42e7e78998063..59ed68c2a773f 100644 --- a/src/test/ui/ast-json/ast-json-output.stdout +++ b/src/test/ui/ast-json/ast-json-output.stdout @@ -1 +1 @@ -{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"NonJoint"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]} +{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"NonJoint"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]} From 1de3ebb39d659d0f1ae85f6b87e2bec96d902d72 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 12 May 2020 20:09:55 -0700 Subject: [PATCH 3/9] Add Extend::{extend_one,extend_reserve} This adds new optional methods on `Extend`: `extend_one` add a single element to the collection, and `extend_reserve` pre-allocates space for the predicted number of incoming elements. These are used in `Iterator` for `partition` and `unzip` as they shuffle elements one-at-a-time into their respective collections. --- src/liballoc/collections/binary_heap.rs | 20 ++++++++++++++ src/liballoc/collections/btree/map.rs | 10 +++++++ src/liballoc/collections/btree/set.rs | 10 +++++++ src/liballoc/collections/linked_list.rs | 10 +++++++ src/liballoc/collections/vec_deque.rs | 20 ++++++++++++++ src/liballoc/lib.rs | 1 + src/liballoc/string.rs | 35 ++++++++++++++++++++++++ src/liballoc/vec.rs | 20 ++++++++++++++ src/libcore/iter/traits/collect.rs | 15 +++++++++- src/libcore/iter/traits/iterator.rs | 14 +++++++--- src/librustc_data_structures/lib.rs | 1 + src/librustc_data_structures/thin_vec.rs | 14 ++++++++++ src/librustc_index/lib.rs | 1 + src/librustc_index/vec.rs | 10 +++++++ src/librustc_infer/lib.rs | 1 + src/librustc_infer/traits/util.rs | 8 ++++++ src/libstd/collections/hash/map.rs | 29 ++++++++++++++++++++ src/libstd/collections/hash/set.rs | 20 ++++++++++++++ src/libstd/lib.rs | 1 + src/libstd/path.rs | 5 ++++ src/libstd/sys_common/wtf8.rs | 11 ++++++++ 21 files changed, 251 insertions(+), 5 deletions(-) diff --git a/src/liballoc/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs index a3ef998918433..c2fe4691b34c0 100644 --- a/src/liballoc/collections/binary_heap.rs +++ b/src/liballoc/collections/binary_heap.rs @@ -1376,6 +1376,16 @@ impl Extend for BinaryHeap { fn extend>(&mut self, iter: I) { >::spec_extend(self, iter); } + + #[inline] + fn extend_one(&mut self, item: T) { + self.push(item); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } } impl> SpecExtend for BinaryHeap { @@ -1406,4 +1416,14 @@ impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BinaryHeap { fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); } + + #[inline] + fn extend_one(&mut self, &item: &'a T) { + self.push(item); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } } diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index c6cb39b1bf511..fa1c09d9ece87 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -1901,6 +1901,11 @@ impl Extend<(K, V)> for BTreeMap { self.insert(k, v); }); } + + #[inline] + fn extend_one(&mut self, (k, v): (K, V)) { + self.insert(k, v); + } } #[stable(feature = "extend_ref", since = "1.2.0")] @@ -1908,6 +1913,11 @@ impl<'a, K: Ord + Copy, V: Copy> Extend<(&'a K, &'a V)> for BTreeMap { fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().map(|(&key, &value)| (key, value))); } + + #[inline] + fn extend_one(&mut self, (&k, &v): (&'a K, &'a V)) { + self.insert(k, v); + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/collections/btree/set.rs b/src/liballoc/collections/btree/set.rs index dee5fb878ff2a..525ef38c32fa2 100644 --- a/src/liballoc/collections/btree/set.rs +++ b/src/liballoc/collections/btree/set.rs @@ -1152,6 +1152,11 @@ impl Extend for BTreeSet { self.insert(elem); }); } + + #[inline] + fn extend_one(&mut self, elem: T) { + self.insert(elem); + } } #[stable(feature = "extend_ref", since = "1.2.0")] @@ -1159,6 +1164,11 @@ impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BTreeSet { fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); } + + #[inline] + fn extend_one(&mut self, &elem: &'a T) { + self.insert(elem); + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs index cc0f07b822741..85f2505f756aa 100644 --- a/src/liballoc/collections/linked_list.rs +++ b/src/liballoc/collections/linked_list.rs @@ -1748,6 +1748,11 @@ impl Extend for LinkedList { fn extend>(&mut self, iter: I) { >::spec_extend(self, iter); } + + #[inline] + fn extend_one(&mut self, elem: T) { + self.push_back(elem); + } } impl SpecExtend for LinkedList { @@ -1767,6 +1772,11 @@ impl<'a, T: 'a + Copy> Extend<&'a T> for LinkedList { fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); } + + #[inline] + fn extend_one(&mut self, &elem: &'a T) { + self.push_back(elem); + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 540649c61b332..ae54d3971baac 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -2881,6 +2881,16 @@ impl Extend for VecDeque { } } } + + #[inline] + fn extend_one(&mut self, elem: A) { + self.push_back(elem); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } } #[stable(feature = "extend_ref", since = "1.2.0")] @@ -2888,6 +2898,16 @@ impl<'a, T: 'a + Copy> Extend<&'a T> for VecDeque { fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); } + + #[inline] + fn extend_one(&mut self, &elem: &T) { + self.push_back(elem); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 7aaa91ee10d97..9bcfc9457f50e 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -93,6 +93,7 @@ #![feature(container_error_extra)] #![feature(dropck_eyepatch)] #![feature(exact_size_is_empty)] +#![feature(extend_one)] #![feature(fmt_internals)] #![feature(fn_traits)] #![feature(fundamental)] diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index f3fe1adebb141..0378ff5362a8b 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -1799,6 +1799,16 @@ impl Extend for String { self.reserve(lower_bound); iterator.for_each(move |c| self.push(c)); } + + #[inline] + fn extend_one(&mut self, c: char) { + self.push(c); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } } #[stable(feature = "extend_ref", since = "1.2.0")] @@ -1806,6 +1816,16 @@ impl<'a> Extend<&'a char> for String { fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); } + + #[inline] + fn extend_one(&mut self, &c: &'a char) { + self.push(c); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1813,6 +1833,11 @@ impl<'a> Extend<&'a str> for String { fn extend>(&mut self, iter: I) { iter.into_iter().for_each(move |s| self.push_str(s)); } + + #[inline] + fn extend_one(&mut self, s: &'a str) { + self.push_str(s); + } } #[stable(feature = "extend_string", since = "1.4.0")] @@ -1820,6 +1845,11 @@ impl Extend for String { fn extend>(&mut self, iter: I) { iter.into_iter().for_each(move |s| self.push_str(&s)); } + + #[inline] + fn extend_one(&mut self, s: String) { + self.push_str(&s); + } } #[stable(feature = "herd_cows", since = "1.19.0")] @@ -1827,6 +1857,11 @@ impl<'a> Extend> for String { fn extend>>(&mut self, iter: I) { iter.into_iter().for_each(move |s| self.push_str(&s)); } + + #[inline] + fn extend_one(&mut self, s: Cow<'a, str>) { + self.push_str(&s); + } } /// A convenience impl that delegates to the impl for `&str`. diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index d26cd77aae4b7..42fb1f8c737b3 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2045,6 +2045,16 @@ impl Extend for Vec { fn extend>(&mut self, iter: I) { >::spec_extend(self, iter.into_iter()) } + + #[inline] + fn extend_one(&mut self, item: T) { + self.push(item); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } } // Specialization trait used for Vec::from_iter and Vec::extend @@ -2316,6 +2326,16 @@ impl<'a, T: 'a + Copy> Extend<&'a T> for Vec { fn extend>(&mut self, iter: I) { self.spec_extend(iter.into_iter()) } + + #[inline] + fn extend_one(&mut self, &item: &'a T) { + self.push(item); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } } macro_rules! __impl_slice_eq1 { diff --git a/src/libcore/iter/traits/collect.rs b/src/libcore/iter/traits/collect.rs index f21ab8dbc3737..da859db545d7e 100644 --- a/src/libcore/iter/traits/collect.rs +++ b/src/libcore/iter/traits/collect.rs @@ -322,7 +322,7 @@ impl IntoIterator for I { pub trait Extend { /// Extends a collection with the contents of an iterator. /// - /// As this is the only method for this trait, the [trait-level] docs + /// As this is the only required method for this trait, the [trait-level] docs /// contain more details. /// /// [trait-level]: trait.Extend.html @@ -341,6 +341,18 @@ pub trait Extend { /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn extend>(&mut self, iter: T); + + /// Extends a collection with exactly one element. + #[unstable(feature = "extend_one", issue = "none")] + fn extend_one(&mut self, item: A) { + self.extend(Some(item)); + } + + /// Reserves capacity in a collection for the given number of additional elements. + /// + /// The default implementation does nothing. + #[unstable(feature = "extend_one", issue = "none")] + fn extend_reserve(&mut self, _additional: usize) {} } #[stable(feature = "extend_for_unit", since = "1.28.0")] @@ -348,4 +360,5 @@ impl Extend<()> for () { fn extend>(&mut self, iter: T) { iter.into_iter().for_each(drop) } + fn extend_one(&mut self, _item: ()) {} } diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index 1c3d95cbb8c35..30a23e7ecd185 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -1700,9 +1700,9 @@ pub trait Iterator { ) -> impl FnMut((), T) + 'a { move |(), x| { if f(&x) { - left.extend(Some(x)); + left.extend_one(x); } else { - right.extend(Some(x)); + right.extend_one(x); } } } @@ -2675,14 +2675,20 @@ pub trait Iterator { us: &'a mut impl Extend, ) -> impl FnMut((), (A, B)) + 'a { move |(), (t, u)| { - ts.extend(Some(t)); - us.extend(Some(u)); + ts.extend_one(t); + us.extend_one(u); } } let mut ts: FromA = Default::default(); let mut us: FromB = Default::default(); + let (lower_bound, _) = self.size_hint(); + if lower_bound > 0 { + ts.extend_reserve(lower_bound); + us.extend_reserve(lower_bound); + } + self.fold((), extend(&mut ts, &mut us)); (ts, us) diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 7ee60176dbead..0b2e7cda1b4cc 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -22,6 +22,7 @@ #![feature(test)] #![feature(associated_type_bounds)] #![feature(thread_id_value)] +#![feature(extend_one)] #![allow(rustc::default_hash_types)] #[macro_use] diff --git a/src/librustc_data_structures/thin_vec.rs b/src/librustc_data_structures/thin_vec.rs index 2befc0aa50487..43002178eb971 100644 --- a/src/librustc_data_structures/thin_vec.rs +++ b/src/librustc_data_structures/thin_vec.rs @@ -53,6 +53,20 @@ impl Extend for ThinVec { ThinVec(None) => *self = iter.into_iter().collect::>().into(), } } + + fn extend_one(&mut self, item: T) { + match *self { + ThinVec(Some(ref mut vec)) => vec.push(item), + ThinVec(None) => *self = vec![item].into(), + } + } + + fn extend_reserve(&mut self, additional: usize) { + match *self { + ThinVec(Some(ref mut vec)) => vec.reserve(additional), + ThinVec(None) => *self = Vec::with_capacity(additional).into(), + } + } } impl, CTX> HashStable for ThinVec { diff --git a/src/librustc_index/lib.rs b/src/librustc_index/lib.rs index e8aa1a209e929..3effc41645011 100644 --- a/src/librustc_index/lib.rs +++ b/src/librustc_index/lib.rs @@ -2,6 +2,7 @@ #![feature(const_if_match)] #![feature(const_fn)] #![feature(const_panic)] +#![feature(extend_one)] #![feature(unboxed_closures)] #![feature(test)] #![feature(fn_traits)] diff --git a/src/librustc_index/vec.rs b/src/librustc_index/vec.rs index 67dcea58cf82b..4dde33283f575 100644 --- a/src/librustc_index/vec.rs +++ b/src/librustc_index/vec.rs @@ -736,6 +736,16 @@ impl Extend for IndexVec { fn extend>(&mut self, iter: J) { self.raw.extend(iter); } + + #[inline] + fn extend_one(&mut self, item: T) { + self.raw.push(item); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.raw.reserve(additional); + } } impl FromIterator for IndexVec { diff --git a/src/librustc_infer/lib.rs b/src/librustc_infer/lib.rs index 28d42cea6d300..ed04ee02b7203 100644 --- a/src/librustc_infer/lib.rs +++ b/src/librustc_infer/lib.rs @@ -16,6 +16,7 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(extend_one)] #![feature(never_type)] #![feature(or_patterns)] #![feature(range_is_empty)] diff --git a/src/librustc_infer/traits/util.rs b/src/librustc_infer/traits/util.rs index 88fc1460475df..46d94f75a2ccd 100644 --- a/src/librustc_infer/traits/util.rs +++ b/src/librustc_infer/traits/util.rs @@ -87,6 +87,14 @@ impl>> Extend for PredicateSet<'tcx> { self.insert(pred.as_ref()); } } + + fn extend_one(&mut self, pred: T) { + self.insert(pred.as_ref()); + } + + fn extend_reserve(&mut self, additional: usize) { + Extend::>::extend_reserve(&mut self.set, additional); + } } /////////////////////////////////////////////////////////////////////////// diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 56cf9be339194..a51f1998e4452 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -2426,6 +2426,24 @@ where fn extend>(&mut self, iter: T) { self.base.extend(iter) } + + #[inline] + fn extend_one(&mut self, (k, v): (K, V)) { + self.base.insert(k, v); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + // self.base.extend_reserve(additional); + // FIXME: hashbrown should implement this method. + // But until then, use the same reservation logic: + + // Reserve the entire hint lower bound if the map is empty. + // Otherwise reserve half the hint (rounded up), so the map + // will only resize twice in the worst case. + let reserve = if self.is_empty() { additional } else { (additional + 1) / 2 }; + self.base.reserve(reserve); + } } #[stable(feature = "hash_extend_copy", since = "1.4.0")] @@ -2439,6 +2457,17 @@ where fn extend>(&mut self, iter: T) { self.base.extend(iter) } + + #[inline] + fn extend_one(&mut self, (&k, &v): (&'a K, &'a V)) { + self.base.insert(k, v); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + // self.base.extend_reserve(additional); + Extend::<(K, V)>::extend_reserve(self, additional) + } } /// `RandomState` is the default state for [`HashMap`] types. diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index ca06457291cae..cb2f829803b85 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -970,6 +970,16 @@ where fn extend>(&mut self, iter: I) { self.map.extend(iter.into_iter().map(|k| (k, ()))); } + + #[inline] + fn extend_one(&mut self, item: T) { + self.map.insert(item, ()); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.map.extend_reserve(additional); + } } #[stable(feature = "hash_extend_copy", since = "1.4.0")] @@ -982,6 +992,16 @@ where fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); } + + #[inline] + fn extend_one(&mut self, &item: &'a T) { + self.map.insert(item, ()); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + Extend::::extend_reserve(self, additional) + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index cc3e613fa3d60..c165bb6ca74c4 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -263,6 +263,7 @@ #![feature(duration_constants)] #![feature(exact_size_is_empty)] #![feature(exhaustive_patterns)] +#![feature(extend_one)] #![feature(external_doc)] #![feature(fn_traits)] #![feature(format_args_nl)] diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 0fe5451bb9564..8ff7508ba6457 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1534,6 +1534,11 @@ impl> iter::Extend

for PathBuf { fn extend>(&mut self, iter: I) { iter.into_iter().for_each(move |p| self.push(p.as_ref())); } + + #[inline] + fn extend_one(&mut self, p: P) { + self.push(p.as_ref()); + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index a98407da44850..a5ba3daba3e87 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -386,6 +386,17 @@ impl Extend for Wtf8Buf { self.bytes.reserve(low); iterator.for_each(move |code_point| self.push(code_point)); } + + #[inline] + fn extend_one(&mut self, code_point: CodePoint) { + self.push(code_point); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + // Lower bound of one byte per code point (ASCII only) + self.bytes.reserve(additional); + } } /// A borrowed slice of well-formed WTF-8 data. From 6a26bb9e8dbeb639c975b2dbe7ae5ce668b15572 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 26 May 2020 14:01:26 -0700 Subject: [PATCH 4/9] Use a canonical name for extend_reserve(additional) Co-authored-by: David Tolnay --- src/libcore/iter/traits/collect.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libcore/iter/traits/collect.rs b/src/libcore/iter/traits/collect.rs index da859db545d7e..4a90aca148547 100644 --- a/src/libcore/iter/traits/collect.rs +++ b/src/libcore/iter/traits/collect.rs @@ -352,7 +352,9 @@ pub trait Extend { /// /// The default implementation does nothing. #[unstable(feature = "extend_one", issue = "none")] - fn extend_reserve(&mut self, _additional: usize) {} + fn extend_reserve(&mut self, additional: usize) { + let _ = additional; + } } #[stable(feature = "extend_for_unit", since = "1.28.0")] From 7795c4bea3d75ffb9ea14a70e3db648a35e09ba8 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 26 May 2020 14:03:34 -0700 Subject: [PATCH 5/9] Remove an old comment from HashMap::extend_reserve --- src/libstd/collections/hash/map.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index a51f1998e4452..5ba5eff44076b 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -2465,7 +2465,6 @@ where #[inline] fn extend_reserve(&mut self, additional: usize) { - // self.base.extend_reserve(additional); Extend::<(K, V)>::extend_reserve(self, additional) } } From 02226e0685b749313d15e71c3028db9dfb62ac11 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 26 May 2020 14:15:29 -0700 Subject: [PATCH 6/9] Add extend_one tracking issue 72631 --- src/libcore/iter/traits/collect.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/iter/traits/collect.rs b/src/libcore/iter/traits/collect.rs index 4a90aca148547..9d20022b6ed6d 100644 --- a/src/libcore/iter/traits/collect.rs +++ b/src/libcore/iter/traits/collect.rs @@ -343,7 +343,7 @@ pub trait Extend { fn extend>(&mut self, iter: T); /// Extends a collection with exactly one element. - #[unstable(feature = "extend_one", issue = "none")] + #[unstable(feature = "extend_one", issue = "72631")] fn extend_one(&mut self, item: A) { self.extend(Some(item)); } @@ -351,7 +351,7 @@ pub trait Extend { /// Reserves capacity in a collection for the given number of additional elements. /// /// The default implementation does nothing. - #[unstable(feature = "extend_one", issue = "none")] + #[unstable(feature = "extend_one", issue = "72631")] fn extend_reserve(&mut self, additional: usize) { let _ = additional; } From 591584e71f7d8a613d586066c8b01c1eecf08f35 Mon Sep 17 00:00:00 2001 From: Mikail Bagishov Date: Tue, 26 May 2020 23:48:36 +0300 Subject: [PATCH 7/9] Add tests for 'impl Default for [T; N]' --- src/libcore/tests/array.rs | 41 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/libcore/tests/array.rs b/src/libcore/tests/array.rs index c2a816f0a7d90..41855a9a8cbab 100644 --- a/src/libcore/tests/array.rs +++ b/src/libcore/tests/array.rs @@ -241,3 +241,44 @@ fn iterator_drops() { } assert_eq!(i.get(), 5); } + +#[test] +fn array_default_impl_avoids_leaks_on_panic() { + use core::sync::atomic::{AtomicUsize, Ordering::Relaxed}; + static COUNTER: AtomicUsize = AtomicUsize::new(0); + #[derive(Debug)] + struct Bomb(usize); + + impl Default for Bomb { + fn default() -> Bomb { + if COUNTER.load(Relaxed) == 3 { + panic!("bomb limit exceeded"); + } + + COUNTER.fetch_add(1, Relaxed); + Bomb(COUNTER.load(Relaxed)) + } + } + + impl Drop for Bomb { + fn drop(&mut self) { + COUNTER.fetch_sub(1, Relaxed); + } + } + + let res = std::panic::catch_unwind(|| <[Bomb; 5]>::default()); + let panic_msg = match res { + Ok(_) => unreachable!(), + Err(p) => p.downcast::<&'static str>().unwrap(), + }; + assert_eq!(*panic_msg, "bomb limit exceeded"); + // check that all bombs are successfully dropped + assert_eq!(COUNTER.load(Relaxed), 0); +} + +#[test] +fn empty_array_is_always_default() { + struct DoesNotImplDefault; + + let _arr = <[DoesNotImplDefault; 0]>::default(); +} From 42ddcd3ec5bfb3004120d9f0114249526416d3cd Mon Sep 17 00:00:00 2001 From: Donough Liu Date: Wed, 27 May 2020 16:16:27 +0800 Subject: [PATCH 8/9] Add myself to .mailmap --- .mailmap | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.mailmap b/.mailmap index 680aa04078f97..da17344c2085e 100644 --- a/.mailmap +++ b/.mailmap @@ -70,6 +70,8 @@ David Manescu David Ross Derek Chiang Derek Chiang (Enchi Jiang) Diggory Hardy Diggory Hardy +Donough Liu +Donough Liu DingMing Liu Dustin Bensing Dylan Braithwaite Dzmitry Malyshau From 5369f4aa57fc72c6f58368bb0f4977975ec2f1e6 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 27 May 2020 21:34:17 +0300 Subject: [PATCH 9/9] rustc_session: Cleanup session creation --- src/librustc_interface/interface.rs | 9 ++--- src/librustc_interface/tests.rs | 12 +++++-- src/librustc_interface/util.rs | 8 ++--- src/librustc_session/parse.rs | 4 +++ src/librustc_session/session.rs | 55 ++++++++--------------------- src/librustdoc/test.rs | 2 +- 6 files changed, 35 insertions(+), 55 deletions(-) diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs index 55f825e150e5e..f127a239eea2c 100644 --- a/src/librustc_interface/interface.rs +++ b/src/librustc_interface/interface.rs @@ -18,7 +18,7 @@ use rustc_session::lint; use rustc_session::parse::{CrateConfig, ParseSess}; use rustc_session::{DiagnosticOutput, Session}; use rustc_span::edition; -use rustc_span::source_map::{FileLoader, FileName, SourceMap}; +use rustc_span::source_map::{FileLoader, FileName}; use std::path::PathBuf; use std::result; use std::sync::{Arc, Mutex}; @@ -31,7 +31,6 @@ pub type Result = result::Result; pub struct Compiler { pub(crate) sess: Lrc, codegen_backend: Lrc>, - source_map: Lrc, pub(crate) input: Input, pub(crate) input_path: Option, pub(crate) output_dir: Option, @@ -49,9 +48,6 @@ impl Compiler { pub fn codegen_backend(&self) -> &Lrc> { &self.codegen_backend } - pub fn source_map(&self) -> &Lrc { - &self.source_map - } pub fn input(&self) -> &Input { &self.input } @@ -168,7 +164,7 @@ pub fn run_compiler_in_existing_thread_pool( f: impl FnOnce(&Compiler) -> R, ) -> R { let registry = &config.registry; - let (sess, codegen_backend, source_map) = util::create_session( + let (sess, codegen_backend) = util::create_session( config.opts, config.crate_cfg, config.diagnostic_output, @@ -181,7 +177,6 @@ pub fn run_compiler_in_existing_thread_pool( let compiler = Compiler { sess, codegen_backend, - source_map, input: config.input, input_path: config.input_path, output_dir: config.output_dir, diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs index d573e11fc4b24..9390bbb34d03a 100644 --- a/src/librustc_interface/tests.rs +++ b/src/librustc_interface/tests.rs @@ -7,11 +7,10 @@ use rustc_session::config::{build_configuration, build_session_options, to_crate use rustc_session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes}; use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath}; use rustc_session::config::{Externs, OutputType, OutputTypes, Sanitizer, SymbolManglingVersion}; -use rustc_session::getopts; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; use rustc_session::utils::NativeLibKind; -use rustc_session::{build_session, Session}; +use rustc_session::{build_session, getopts, DiagnosticOutput, Session}; use rustc_span::edition::{Edition, DEFAULT_EDITION}; use rustc_span::symbol::sym; use rustc_span::SourceFileHashAlgorithm; @@ -32,7 +31,14 @@ fn build_session_options_and_crate_config(matches: getopts::Matches) -> (Options fn mk_session(matches: getopts::Matches) -> (Session, CfgSpecs) { let registry = registry::Registry::new(&[]); let (sessopts, cfg) = build_session_options_and_crate_config(matches); - let sess = build_session(sessopts, None, registry); + let sess = build_session( + sessopts, + None, + registry, + DiagnosticOutput::Default, + Default::default(), + None, + ); (sess, cfg) } diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 7eaaff05fb5f0..924908e572487 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -23,7 +23,7 @@ use rustc_session::parse::CrateConfig; use rustc_session::CrateDisambiguator; use rustc_session::{early_error, filesearch, output, DiagnosticOutput, Session}; use rustc_span::edition::Edition; -use rustc_span::source_map::{FileLoader, SourceMap}; +use rustc_span::source_map::FileLoader; use rustc_span::symbol::{sym, Symbol}; use smallvec::SmallVec; use std::env; @@ -65,8 +65,8 @@ pub fn create_session( input_path: Option, lint_caps: FxHashMap, descriptions: Registry, -) -> (Lrc, Lrc>, Lrc) { - let (mut sess, source_map) = session::build_session_with_source_map( +) -> (Lrc, Lrc>) { + let mut sess = session::build_session( sopts, input_path, descriptions, @@ -81,7 +81,7 @@ pub fn create_session( add_configuration(&mut cfg, &mut sess, &*codegen_backend); sess.parse_sess.config = cfg; - (Lrc::new(sess), Lrc::new(codegen_backend), source_map) + (Lrc::new(sess), Lrc::new(codegen_backend)) } const STACK_SIZE: usize = 8 * 1024 * 1024; diff --git a/src/librustc_session/parse.rs b/src/librustc_session/parse.rs index 746e3536ce908..233761dbed7de 100644 --- a/src/librustc_session/parse.rs +++ b/src/librustc_session/parse.rs @@ -174,6 +174,10 @@ impl ParseSess { &self.source_map } + pub fn clone_source_map(&self) -> Lrc { + self.source_map.clone() + } + pub fn buffer_lint( &self, lint: &'static Lint, diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs index f2f02cb649463..ba9741b1890f6 100644 --- a/src/librustc_session/session.rs +++ b/src/librustc_session/session.rs @@ -21,7 +21,7 @@ use rustc_errors::json::JsonEmitter; use rustc_errors::registry::Registry; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId, ErrorReported}; use rustc_span::edition::Edition; -use rustc_span::source_map::{self, FileLoader, MultiSpan, RealFileLoader, SourceMap, Span}; +use rustc_span::source_map::{FileLoader, MultiSpan, RealFileLoader, SourceMap, Span}; use rustc_span::{SourceFileHashAlgorithm, Symbol}; use rustc_target::asm::InlineAsmArch; use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel}; @@ -481,7 +481,7 @@ impl Session { } #[inline] - pub fn source_map(&self) -> &source_map::SourceMap { + pub fn source_map(&self) -> &SourceMap { self.parse_sess.source_map() } pub fn verbose(&self) -> bool { @@ -984,26 +984,10 @@ impl Session { } } -pub fn build_session( - sopts: config::Options, - local_crate_source_file: Option, - registry: rustc_errors::registry::Registry, -) -> Session { - build_session_with_source_map( - sopts, - local_crate_source_file, - registry, - DiagnosticOutput::Default, - Default::default(), - None, - ) - .0 -} - fn default_emitter( sopts: &config::Options, registry: rustc_errors::registry::Registry, - source_map: &Lrc, + source_map: Lrc, emitter_dest: Option>, ) -> Box { let macro_backtrace = sopts.debugging_opts.macro_backtrace; @@ -1012,17 +996,14 @@ fn default_emitter( let (short, color_config) = kind.unzip(); if let HumanReadableErrorType::AnnotateSnippet(_) = kind { - let emitter = AnnotateSnippetEmitterWriter::new( - Some(source_map.clone()), - short, - macro_backtrace, - ); + let emitter = + AnnotateSnippetEmitterWriter::new(Some(source_map), short, macro_backtrace); Box::new(emitter.ui_testing(sopts.debugging_opts.ui_testing)) } else { let emitter = match dst { None => EmitterWriter::stderr( color_config, - Some(source_map.clone()), + Some(source_map), short, sopts.debugging_opts.teach, sopts.debugging_opts.terminal_width, @@ -1030,7 +1011,7 @@ fn default_emitter( ), Some(dst) => EmitterWriter::new( dst, - Some(source_map.clone()), + Some(source_map), short, false, // no teach messages when writing to a buffer false, // no colors when writing to a buffer @@ -1042,20 +1023,14 @@ fn default_emitter( } } (config::ErrorOutputType::Json { pretty, json_rendered }, None) => Box::new( - JsonEmitter::stderr( - Some(registry), - source_map.clone(), - pretty, - json_rendered, - macro_backtrace, - ) - .ui_testing(sopts.debugging_opts.ui_testing), + JsonEmitter::stderr(Some(registry), source_map, pretty, json_rendered, macro_backtrace) + .ui_testing(sopts.debugging_opts.ui_testing), ), (config::ErrorOutputType::Json { pretty, json_rendered }, Some(dst)) => Box::new( JsonEmitter::new( dst, Some(registry), - source_map.clone(), + source_map, pretty, json_rendered, macro_backtrace, @@ -1070,14 +1045,14 @@ pub enum DiagnosticOutput { Raw(Box), } -pub fn build_session_with_source_map( +pub fn build_session( sopts: config::Options, local_crate_source_file: Option, registry: rustc_errors::registry::Registry, diagnostics_output: DiagnosticOutput, driver_lint_caps: FxHashMap, file_loader: Option>, -) -> (Session, Lrc) { +) -> Session { // FIXME: This is not general enough to make the warning lint completely override // normal diagnostic warnings, since the warning lint can also be denied and changed // later via the source code. @@ -1115,7 +1090,7 @@ pub fn build_session_with_source_map( sopts.file_path_mapping(), hash_kind, )); - let emitter = default_emitter(&sopts, registry, &source_map, write_dest); + let emitter = default_emitter(&sopts, registry, source_map.clone(), write_dest); let span_diagnostic = rustc_errors::Handler::with_emitter_and_flags( emitter, @@ -1143,7 +1118,7 @@ pub fn build_session_with_source_map( None }; - let parse_sess = ParseSess::with_span_handler(span_diagnostic, source_map.clone()); + let parse_sess = ParseSess::with_span_handler(span_diagnostic, source_map); let sysroot = match &sopts.maybe_sysroot { Some(sysroot) => sysroot.clone(), None => filesearch::get_or_default_sysroot(), @@ -1266,7 +1241,7 @@ pub fn build_session_with_source_map( validate_commandline_args_with_session_available(&sess); - (sess, source_map) + sess } // If it is useful to have a Session available already for validating a diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 284e6d421ee2f..85ba4cbdc7e1b 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -114,7 +114,7 @@ pub fn run(options: Options) -> Result<(), String> { options, false, opts, - Some(compiler.source_map().clone()), + Some(compiler.session().parse_sess.clone_source_map()), None, enable_per_target_ignores, );