From ea4e5c27a9fe52d175f6cdf5af4d2079660a5540 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Wed, 16 Mar 2022 13:41:11 +0100 Subject: BTree: evaluate static type-related check at compile time --- library/alloc/src/collections/btree/node.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 44f5bc850b8..86c46010a4e 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -315,7 +315,7 @@ impl NodeRef pub fn ascend( self, ) -> Result, marker::Edge>, Self> { - assert!(BorrowType::PERMITS_TRAVERSAL); + let _ = BorrowType::TRAVERSAL_PERMIT; // We need to use raw pointers to nodes because, if BorrowType is marker::ValMut, // there might be outstanding mutable references to values that we must not invalidate. let leaf_ptr: *const _ = Self::as_leaf_ptr(&self); @@ -986,7 +986,7 @@ impl /// `edge.descend().ascend().unwrap()` and `node.ascend().unwrap().descend()` should /// both, upon success, do nothing. pub fn descend(self) -> NodeRef { - assert!(BorrowType::PERMITS_TRAVERSAL); + let _ = BorrowType::TRAVERSAL_PERMIT; // We need to use raw pointers to nodes because, if BorrowType is // marker::ValMut, there might be outstanding mutable references to // values that we must not invalidate. There's no worry accessing the @@ -1637,15 +1637,17 @@ pub mod marker { pub struct ValMut<'a>(PhantomData<&'a mut ()>); pub trait BorrowType { - // Whether node references of this borrow type allow traversing - // to other nodes in the tree. - const PERMITS_TRAVERSAL: bool = true; + // If node references of this borrow type allow traversing to other + // nodes in the tree, this constant can be evaluated. Thus reading it + // serves as a compile-time assertion. + const TRAVERSAL_PERMIT: () = (); } impl BorrowType for Owned { - // Traversal isn't needed, it happens using the result of `borrow_mut`. + // Reject evaluation, because traversal isn't needed. Instead traversal + // happens using the result of `borrow_mut`. // By disabling traversal, and only creating new references to roots, // we know that every reference of the `Owned` type is to a root node. - const PERMITS_TRAVERSAL: bool = false; + const TRAVERSAL_PERMIT: () = panic!(); } impl BorrowType for Dying {} impl<'a> BorrowType for Immut<'a> {} -- cgit 1.4.1-3-g733a5 From 50c98a8c46e7b6aa7740448645905bfac024f191 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sun, 27 Mar 2022 22:02:06 +0400 Subject: Add vec::Drain{,Filter}::keep_rest These methods allow to cancel draining of unyielded elements. --- library/alloc/src/vec/drain.rs | 55 +++++++++++++++++++++++++++++++- library/alloc/src/vec/drain_filter.rs | 41 ++++++++++++++++++++++-- library/alloc/tests/lib.rs | 1 + library/alloc/tests/vec.rs | 59 +++++++++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+), 3 deletions(-) diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs index 5cdee0bd4da..3e350c2b38e 100644 --- a/library/alloc/src/vec/drain.rs +++ b/library/alloc/src/vec/drain.rs @@ -1,7 +1,7 @@ use crate::alloc::{Allocator, Global}; use core::fmt; use core::iter::{FusedIterator, TrustedLen}; -use core::mem; +use core::mem::{self, ManuallyDrop}; use core::ptr::{self, NonNull}; use core::slice::{self}; @@ -65,6 +65,59 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> { pub fn allocator(&self) -> &A { unsafe { self.vec.as_ref().allocator() } } + + /// Keep unyielded elements in the source `Vec`. + #[unstable(feature = "drain_keep_rest", issue = "none")] + pub fn keep_rest(self) { + // At this moment layout looks like this: + // + // [head] [yielded by next] [unyielded] [yielded by next_back] [tail] + // ^-- start \_________/-- unyielded_len \____/-- self.tail_len + // ^-- unyielded_ptr ^-- tail + // + // Normally `Drop` impl would drop [unyielded] and then move [tail] to the `start`. + // Here we want to + // 1. Move [unyielded] to `start` + // 2. Move [tail] to a new start at `start + len(unyielded)` + // 3. Update length of the original vec to `len(head) + len(unyielded) + len(tail)` + // a. In case of ZST, this is the only thing we want to do + // 4. Do *not* drop self, as everything is put in a consistent state already, there is nothing to do + let mut this = ManuallyDrop::new(self); + + unsafe { + let source_vec = this.vec.as_mut(); + + let start = source_vec.len(); + let tail = this.tail_start; + + let unyielded_len = this.iter.len(); + let unyielded_ptr = this.iter.as_slice().as_ptr(); + + // ZSTs have no identity, so we don't need to move them around. + let needs_move = mem::size_of::() != 0; + + if needs_move { + let start_ptr = source_vec.as_mut_ptr().add(start); + + // memmove back unyielded elements + if unyielded_ptr != start_ptr { + let src = unyielded_ptr; + let dst = start_ptr; + + ptr::copy(src, dst, unyielded_len); + } + + // memmove back untouched tail + if tail != (start + unyielded_len) { + let src = source_vec.as_ptr().add(tail); + let dst = start_ptr.add(unyielded_len); + ptr::copy(src, dst, this.tail_len); + } + } + + source_vec.set_len(start + unyielded_len + this.tail_len); + } + } } #[stable(feature = "vec_drain_as_slice", since = "1.46.0")] diff --git a/library/alloc/src/vec/drain_filter.rs b/library/alloc/src/vec/drain_filter.rs index 3c37c92ae44..a5c1eab94ee 100644 --- a/library/alloc/src/vec/drain_filter.rs +++ b/library/alloc/src/vec/drain_filter.rs @@ -1,6 +1,7 @@ use crate::alloc::{Allocator, Global}; -use core::ptr::{self}; -use core::slice::{self}; +use core::mem::{self, ManuallyDrop}; +use core::ptr; +use core::slice; use super::Vec; @@ -54,6 +55,42 @@ where pub fn allocator(&self) -> &A { self.vec.allocator() } + + /// Keep unyielded elements in the source `Vec`. + #[unstable(feature = "drain_keep_rest", issue = "none")] + pub fn keep_rest(self) { + // At this moment layout looks like this: + // + // _____________________/-- old_len + // / \ + // [kept] [yielded] [tail] + // \_______/ ^-- idx + // \-- del + // + // Normally `Drop` impl would drop [tail] (via .for_each(drop), ie still calling `pred`) + // + // 1. Move [tail] after [kept] + // 2. Update length of the original vec to `old_len - del` + // a. In case of ZST, this is the only thing we want to do + // 3. Do *not* drop self, as everything is put in a consistent state already, there is nothing to do + let mut this = ManuallyDrop::new(self); + + unsafe { + // ZSTs have no identity, so we don't need to move them around. + let needs_move = mem::size_of::() != 0; + + if needs_move && this.idx < this.old_len && this.del > 0 { + let ptr = this.vec.as_mut_ptr(); + let src = ptr.add(this.idx); + let dst = src.sub(this.del); + let tail_len = this.old_len - this.idx; + src.copy_to(dst, tail_len); + } + + let new_len = this.old_len - this.del; + this.vec.set_len(new_len); + } + } } #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index ffc7944ec7e..455bd92361e 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -45,6 +45,7 @@ #![feature(bench_black_box)] #![feature(strict_provenance)] #![feature(once_cell)] +#![feature(drain_keep_rest)] use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index cc768c73c0e..946380162e7 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -793,6 +793,36 @@ fn test_drain_leak() { assert_eq!(v, vec![D(0, false), D(1, false), D(6, false),]); } +#[test] +fn test_drain_keep_rest() { + let mut v = vec![0, 1, 2, 3, 4, 5, 6]; + let mut drain = v.drain(1..6); + assert_eq!(drain.next(), Some(1)); + assert_eq!(drain.next_back(), Some(5)); + assert_eq!(drain.next(), Some(2)); + + drain.keep_rest(); + assert_eq!(v, &[0, 3, 4, 6]); +} + +#[test] +fn test_drain_keep_rest_all() { + let mut v = vec![0, 1, 2, 3, 4, 5, 6]; + v.drain(1..6).keep_rest(); + assert_eq!(v, &[0, 1, 2, 3, 4, 5, 6]); +} + +#[test] +fn test_drain_keep_rest_none() { + let mut v = vec![0, 1, 2, 3, 4, 5, 6]; + let mut drain = v.drain(1..6); + + drain.by_ref().for_each(drop); + + drain.keep_rest(); + assert_eq!(v, &[0, 6]); +} + #[test] fn test_splice() { let mut v = vec![1, 2, 3, 4, 5]; @@ -1478,6 +1508,35 @@ fn drain_filter_unconsumed() { assert_eq!(vec, [2, 4]); } +#[test] +fn test_drain_filter_keep_rest() { + let mut v = vec![0, 1, 2, 3, 4, 5, 6]; + let mut drain = v.drain_filter(|&mut x| x % 2 == 0); + assert_eq!(drain.next(), Some(0)); + assert_eq!(drain.next(), Some(2)); + + drain.keep_rest(); + assert_eq!(v, &[1, 3, 4, 5, 6]); +} + +#[test] +fn test_drain_filter_keep_rest_all() { + let mut v = vec![0, 1, 2, 3, 4, 5, 6]; + v.drain_filter(|_| true).keep_rest(); + assert_eq!(v, &[0, 1, 2, 3, 4, 5, 6]); +} + +#[test] +fn test_drain_filter_keep_rest_none() { + let mut v = vec![0, 1, 2, 3, 4, 5, 6]; + let mut drain = v.drain_filter(|_| true); + + drain.by_ref().for_each(drop); + + drain.keep_rest(); + assert_eq!(v, &[]); +} + #[test] fn test_reserve_exact() { // This is all the same as test_reserve -- cgit 1.4.1-3-g733a5 From 5454bca1b4b14706529e496ae6df8069682d24ae Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 10 Jun 2022 19:54:53 +0100 Subject: net listen backlog set to negative on Linux. it will be 4076 (from 5.4) or 128. --- library/std/src/os/unix/net/listener.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/library/std/src/os/unix/net/listener.rs b/library/std/src/os/unix/net/listener.rs index 8e11d32f130..3b31c000f25 100644 --- a/library/std/src/os/unix/net/listener.rs +++ b/library/std/src/os/unix/net/listener.rs @@ -73,9 +73,13 @@ impl UnixListener { unsafe { let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; let (addr, len) = sockaddr_un(path.as_ref())?; + #[cfg(target_os = "linux")] + const backlog: libc::c_int = -1; + #[cfg(not(target_os = "linux"))] + const backlog: libc::c_int = 128; cvt(libc::bind(inner.as_inner().as_raw_fd(), &addr as *const _ as *const _, len as _))?; - cvt(libc::listen(inner.as_inner().as_raw_fd(), 128))?; + cvt(libc::listen(inner.as_inner().as_raw_fd(), backlog))?; Ok(UnixListener(inner)) } @@ -109,12 +113,16 @@ impl UnixListener { pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result { unsafe { let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; + #[cfg(target_os = "linux")] + const backlog: libc::c_int = -1; + #[cfg(not(target_os = "linux"))] + const backlog: libc::c_int = 128; cvt(libc::bind( inner.as_raw_fd(), &socket_addr.addr as *const _ as *const _, socket_addr.len as _, ))?; - cvt(libc::listen(inner.as_raw_fd(), 128))?; + cvt(libc::listen(inner.as_raw_fd(), backlog))?; Ok(UnixListener(inner)) } } -- cgit 1.4.1-3-g733a5 From 90abfe9ce27c81808e3f74861072df6734f6a45d Mon Sep 17 00:00:00 2001 From: ouz-a Date: Fri, 17 Jun 2022 16:34:00 +0300 Subject: expand inner `or` pattern --- compiler/rustc_mir_build/src/thir/pattern/usefulness.rs | 12 +++++++++++- src/test/ui/or-patterns/inner-or-pat-2.rs | 13 +++++++++++++ src/test/ui/or-patterns/inner-or-pat-2.stderr | 11 +++++++++++ src/test/ui/or-patterns/inner-or-pat-3.rs | 15 +++++++++++++++ src/test/ui/or-patterns/inner-or-pat-4.rs | 13 +++++++++++++ src/test/ui/or-patterns/inner-or-pat-4.stderr | 11 +++++++++++ src/test/ui/or-patterns/inner-or-pat.rs | 14 ++++++++++++++ 7 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/or-patterns/inner-or-pat-2.rs create mode 100644 src/test/ui/or-patterns/inner-or-pat-2.stderr create mode 100644 src/test/ui/or-patterns/inner-or-pat-3.rs create mode 100644 src/test/ui/or-patterns/inner-or-pat-4.rs create mode 100644 src/test/ui/or-patterns/inner-or-pat-4.stderr create mode 100644 src/test/ui/or-patterns/inner-or-pat.rs diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index 9e7a267ecbd..5bb2f00d3cf 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -453,7 +453,17 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> { /// expands it. fn push(&mut self, row: PatStack<'p, 'tcx>) { if !row.is_empty() && row.head().is_or_pat() { - self.patterns.extend(row.expand_or_pat()); + let pats = row.expand_or_pat(); + let mut no_inner_or = true; + for pat in pats { + if !pat.is_empty() && pat.head().is_or_pat() { + self.patterns.extend(pat.expand_or_pat()); + no_inner_or = false; + } + } + if no_inner_or { + self.patterns.extend(row.expand_or_pat()); + } } else { self.patterns.push(row); } diff --git a/src/test/ui/or-patterns/inner-or-pat-2.rs b/src/test/ui/or-patterns/inner-or-pat-2.rs new file mode 100644 index 00000000000..3053d973453 --- /dev/null +++ b/src/test/ui/or-patterns/inner-or-pat-2.rs @@ -0,0 +1,13 @@ +#[allow(unused_variables)] +#[allow(unused_parens)] +fn main() { + let x = "foo"; + match x { + x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | () | "nop") | ("hey" | "gg")) | + //~^ ERROR mismatched types + x @ ("black" | "pink") | + x @ ("red" | "blue") => { + } + _ => (), + } +} diff --git a/src/test/ui/or-patterns/inner-or-pat-2.stderr b/src/test/ui/or-patterns/inner-or-pat-2.stderr new file mode 100644 index 00000000000..505b6c64a22 --- /dev/null +++ b/src/test/ui/or-patterns/inner-or-pat-2.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/inner-or-pat-2.rs:6:54 + | +LL | match x { + | - this expression has type `&str` +LL | x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | () | "nop") | ("hey" | "gg")) | + | ^^ expected `str`, found `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/or-patterns/inner-or-pat-3.rs b/src/test/ui/or-patterns/inner-or-pat-3.rs new file mode 100644 index 00000000000..f6fe8a4dd59 --- /dev/null +++ b/src/test/ui/or-patterns/inner-or-pat-3.rs @@ -0,0 +1,15 @@ +// run-pass + +#[allow(unreachable_patterns)] +#[allow(unused_variables)] +#[allow(unused_parens)] +fn main() { + let x = "foo"; + + match x { + x @ ("foo" | "bar") | + (x @ "red" | (x @ "blue" | x @ "red")) => { + } + _ => (), + } +} diff --git a/src/test/ui/or-patterns/inner-or-pat-4.rs b/src/test/ui/or-patterns/inner-or-pat-4.rs new file mode 100644 index 00000000000..fe771e2e930 --- /dev/null +++ b/src/test/ui/or-patterns/inner-or-pat-4.rs @@ -0,0 +1,13 @@ +#[allow(unused_variables)] +#[allow(unused_parens)] +fn main() { + let x = "foo"; + + match x { + x @ ("foo" | "bar") | + (x @ "red" | (x @ "blue" | "red")) => { + //~^ variable `x` is not bound in all patterns + } + _ => (), + } +} diff --git a/src/test/ui/or-patterns/inner-or-pat-4.stderr b/src/test/ui/or-patterns/inner-or-pat-4.stderr new file mode 100644 index 00000000000..177c7f98312 --- /dev/null +++ b/src/test/ui/or-patterns/inner-or-pat-4.stderr @@ -0,0 +1,11 @@ +error[E0408]: variable `x` is not bound in all patterns + --> $DIR/inner-or-pat-4.rs:8:37 + | +LL | (x @ "red" | (x @ "blue" | "red")) => { + | - ^^^^^ pattern doesn't bind `x` + | | + | variable not in all patterns + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0408`. diff --git a/src/test/ui/or-patterns/inner-or-pat.rs b/src/test/ui/or-patterns/inner-or-pat.rs new file mode 100644 index 00000000000..c49b04aa65b --- /dev/null +++ b/src/test/ui/or-patterns/inner-or-pat.rs @@ -0,0 +1,14 @@ +// run-pass + +#[allow(unused_variables)] +#[allow(unused_parens)] +fn main() { + let x = "foo"; + match x { + x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | "no" | "nop") | ("hey" | "gg")) | + x @ ("black" | "pink") | + x @ ("red" | "blue") => { + } + _ => (), + } +} -- cgit 1.4.1-3-g733a5 From caf8bcceff301b4fa3414e3f21813581a8d758a3 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Sat, 7 May 2022 09:34:57 -0700 Subject: Optimize `Wtf8Buf::into_string` for the case where it contains UTF-8. Add a `is_known_utf8` flag to `Wtf8Buf`, which tracks whether the string is known to contain UTF-8. This is efficiently computed in many common situations, such as when a `Wtf8Buf` is constructed from a `String` or `&str`, or with `Wtf8Buf::from_wide` which is already doing UTF-16 decoding and already checking for surrogates. This makes `OsString::into_string` O(1) rather than O(N) on Windows in common cases. And, it eliminates the need to scan through the string for surrogates in `Args::next` and `Vars::next`, because the strings are already being translated with `Wtf8Buf::from_wide`. Many things on Windows construct `OsString`s with `Wtf8Buf::from_wide`, such as `DirEntry::file_name` and `fs::read_link`, so with this patch, users of those functions can subsequently call `.into_string()` without paying for an extra scan through the string for surrogates. --- library/std/src/sys/windows/os_str.rs | 4 +- library/std/src/sys_common/wtf8.rs | 98 ++++++++-- library/std/src/sys_common/wtf8/tests.rs | 303 +++++++++++++++++++++++++++++-- 3 files changed, 366 insertions(+), 39 deletions(-) diff --git a/library/std/src/sys/windows/os_str.rs b/library/std/src/sys/windows/os_str.rs index 11883f15022..4bdd8c505ff 100644 --- a/library/std/src/sys/windows/os_str.rs +++ b/library/std/src/sys/windows/os_str.rs @@ -164,9 +164,7 @@ impl Slice { } pub fn to_owned(&self) -> Buf { - let mut buf = Wtf8Buf::with_capacity(self.inner.len()); - buf.push_wtf8(&self.inner); - Buf { inner: buf } + Buf { inner: self.inner.to_owned() } } pub fn clone_into(&self, buf: &mut Buf) { diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs index 57fa4989358..a674ced88bb 100644 --- a/library/std/src/sys_common/wtf8.rs +++ b/library/std/src/sys_common/wtf8.rs @@ -89,6 +89,24 @@ impl CodePoint { self.value } + /// Returns the numeric value of the code point if it is a leading surrogate. + #[inline] + pub fn to_lead_surrogate(&self) -> Option { + match self.value { + lead @ 0xD800..=0xDBFF => Some(lead as u16), + _ => None, + } + } + + /// Returns the numeric value of the code point if it is a trailing surrogate. + #[inline] + pub fn to_trail_surrogate(&self) -> Option { + match self.value { + trail @ 0xDC00..=0xDFFF => Some(trail as u16), + _ => None, + } + } + /// Optionally returns a Unicode scalar value for the code point. /// /// Returns `None` if the code point is a surrogate (from U+D800 to U+DFFF). @@ -117,6 +135,14 @@ impl CodePoint { #[derive(Eq, PartialEq, Ord, PartialOrd, Clone)] pub struct Wtf8Buf { bytes: Vec, + + /// Do we know that `bytes` holds a valid UTF-8 encoding? We can easily + /// know this if we're constructed from a `String` or `&str`. + /// + /// It is possible for `bytes` to have valid UTF-8 without this being + /// set, such as when we're concatenating `&Wtf8`'s and surrogates become + /// paired, as we don't bother to rescan the entire string. + is_known_utf8: bool, } impl ops::Deref for Wtf8Buf { @@ -147,13 +173,13 @@ impl Wtf8Buf { /// Creates a new, empty WTF-8 string. #[inline] pub fn new() -> Wtf8Buf { - Wtf8Buf { bytes: Vec::new() } + Wtf8Buf { bytes: Vec::new(), is_known_utf8: true } } /// Creates a new, empty WTF-8 string with pre-allocated capacity for `capacity` bytes. #[inline] pub fn with_capacity(capacity: usize) -> Wtf8Buf { - Wtf8Buf { bytes: Vec::with_capacity(capacity) } + Wtf8Buf { bytes: Vec::with_capacity(capacity), is_known_utf8: true } } /// Creates a WTF-8 string from a UTF-8 `String`. @@ -163,7 +189,7 @@ impl Wtf8Buf { /// Since WTF-8 is a superset of UTF-8, this always succeeds. #[inline] pub fn from_string(string: String) -> Wtf8Buf { - Wtf8Buf { bytes: string.into_bytes() } + Wtf8Buf { bytes: string.into_bytes(), is_known_utf8: true } } /// Creates a WTF-8 string from a UTF-8 `&str` slice. @@ -173,11 +199,12 @@ impl Wtf8Buf { /// Since WTF-8 is a superset of UTF-8, this always succeeds. #[inline] pub fn from_str(str: &str) -> Wtf8Buf { - Wtf8Buf { bytes: <[_]>::to_vec(str.as_bytes()) } + Wtf8Buf { bytes: <[_]>::to_vec(str.as_bytes()), is_known_utf8: true } } pub fn clear(&mut self) { - self.bytes.clear() + self.bytes.clear(); + self.is_known_utf8 = true; } /// Creates a WTF-8 string from a potentially ill-formed UTF-16 slice of 16-bit code units. @@ -195,7 +222,9 @@ impl Wtf8Buf { let code_point = unsafe { CodePoint::from_u32_unchecked(surrogate as u32) }; // Skip the WTF-8 concatenation check, // surrogate pairs are already decoded by decode_utf16 - string.push_code_point_unchecked(code_point) + string.push_code_point_unchecked(code_point); + // The string now contains an unpaired surrogate. + string.is_known_utf8 = false; } } } @@ -203,7 +232,7 @@ impl Wtf8Buf { } /// Copied from String::push - /// This does **not** include the WTF-8 concatenation check. + /// This does **not** include the WTF-8 concatenation check or `is_known_utf8` check. fn push_code_point_unchecked(&mut self, code_point: CodePoint) { let mut bytes = [0; 4]; let bytes = char::encode_utf8_raw(code_point.value, &mut bytes); @@ -217,6 +246,9 @@ impl Wtf8Buf { #[inline] pub fn as_mut_slice(&mut self) -> &mut Wtf8 { + // Safety: `Wtf8` doesn't expose any way to mutate the bytes that would + // cause them to change from well-formed UTF-8 to ill-formed UTF-8, + // which would break the assumptions of the `is_known_utf8` field. unsafe { Wtf8::from_mut_bytes_unchecked(&mut self.bytes) } } @@ -313,7 +345,15 @@ impl Wtf8Buf { self.push_char(decode_surrogate_pair(lead, trail)); self.bytes.extend_from_slice(other_without_trail_surrogate); } - _ => self.bytes.extend_from_slice(&other.bytes), + _ => { + self.bytes.extend_from_slice(&other.bytes); + + // If we're pushing a string containing a surrogate, we may no + // longer have UTF-8. + if other.next_surrogate(0).is_some() { + self.is_known_utf8 = false; + } + } } } @@ -330,13 +370,19 @@ impl Wtf8Buf { /// like concatenating ill-formed UTF-16 strings effectively would. #[inline] pub fn push(&mut self, code_point: CodePoint) { - if let trail @ 0xDC00..=0xDFFF = code_point.to_u32() { + if let Some(trail) = code_point.to_trail_surrogate() { if let Some(lead) = (&*self).final_lead_surrogate() { let len_without_lead_surrogate = self.len() - 3; self.bytes.truncate(len_without_lead_surrogate); - self.push_char(decode_surrogate_pair(lead, trail as u16)); + self.push_char(decode_surrogate_pair(lead, trail)); return; } + + // We're pushing a trailing surrogate. + self.is_known_utf8 = false; + } else if code_point.to_lead_surrogate().is_some() { + // We're pushing a leading surrogate. + self.is_known_utf8 = false; } // No newly paired surrogates at the boundary. @@ -363,9 +409,10 @@ impl Wtf8Buf { /// (that is, if the string contains surrogates), /// the original WTF-8 string is returned instead. pub fn into_string(self) -> Result { - match self.next_surrogate(0) { - None => Ok(unsafe { String::from_utf8_unchecked(self.bytes) }), - Some(_) => Err(self), + if self.is_known_utf8 || self.next_surrogate(0).is_none() { + Ok(unsafe { String::from_utf8_unchecked(self.bytes) }) + } else { + Err(self) } } @@ -375,6 +422,11 @@ impl Wtf8Buf { /// /// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”) pub fn into_string_lossy(mut self) -> String { + // Fast path: If we already have UTF-8, we can return it immediately. + if self.is_known_utf8 { + return unsafe { String::from_utf8_unchecked(self.bytes) }; + } + let mut pos = 0; loop { match self.next_surrogate(pos) { @@ -397,7 +449,7 @@ impl Wtf8Buf { /// Converts a `Box` into a `Wtf8Buf`. pub fn from_box(boxed: Box) -> Wtf8Buf { let bytes: Box<[u8]> = unsafe { mem::transmute(boxed) }; - Wtf8Buf { bytes: bytes.into_vec() } + Wtf8Buf { bytes: bytes.into_vec(), is_known_utf8: false } } } @@ -575,6 +627,11 @@ impl Wtf8 { } } + /// Creates an owned `Wtf8Buf` from a borrowed `Wtf8`. + pub fn to_owned(&self) -> Wtf8Buf { + Wtf8Buf { bytes: self.bytes.to_vec(), is_known_utf8: false } + } + /// Lossily converts the string to UTF-8. /// Returns a UTF-8 `&str` slice if the contents are well-formed in UTF-8. /// @@ -664,7 +721,8 @@ impl Wtf8 { } pub fn clone_into(&self, buf: &mut Wtf8Buf) { - self.bytes.clone_into(&mut buf.bytes) + self.bytes.clone_into(&mut buf.bytes); + buf.is_known_utf8 = false; } /// Boxes this `Wtf8`. @@ -704,12 +762,18 @@ impl Wtf8 { #[inline] pub fn to_ascii_lowercase(&self) -> Wtf8Buf { - Wtf8Buf { bytes: self.bytes.to_ascii_lowercase() } + Wtf8Buf { + bytes: self.bytes.to_ascii_lowercase(), + is_known_utf8: self.next_surrogate(0).is_none(), + } } #[inline] pub fn to_ascii_uppercase(&self) -> Wtf8Buf { - Wtf8Buf { bytes: self.bytes.to_ascii_uppercase() } + Wtf8Buf { + bytes: self.bytes.to_ascii_uppercase(), + is_known_utf8: self.next_surrogate(0).is_none(), + } } #[inline] diff --git a/library/std/src/sys_common/wtf8/tests.rs b/library/std/src/sys_common/wtf8/tests.rs index 931996791fb..8360e3da215 100644 --- a/library/std/src/sys_common/wtf8/tests.rs +++ b/library/std/src/sys_common/wtf8/tests.rs @@ -19,6 +19,36 @@ fn code_point_to_u32() { assert_eq!(c(0x10FFFF).to_u32(), 0x10FFFF); } +#[test] +fn code_point_to_lead_surrogate() { + fn c(value: u32) -> CodePoint { + CodePoint::from_u32(value).unwrap() + } + assert_eq!(c(0).to_lead_surrogate(), None); + assert_eq!(c(0xE9).to_lead_surrogate(), None); + assert_eq!(c(0xD800).to_lead_surrogate(), Some(0xD800)); + assert_eq!(c(0xDBFF).to_lead_surrogate(), Some(0xDBFF)); + assert_eq!(c(0xDC00).to_lead_surrogate(), None); + assert_eq!(c(0xDFFF).to_lead_surrogate(), None); + assert_eq!(c(0x1F4A9).to_lead_surrogate(), None); + assert_eq!(c(0x10FFFF).to_lead_surrogate(), None); +} + +#[test] +fn code_point_to_trail_surrogate() { + fn c(value: u32) -> CodePoint { + CodePoint::from_u32(value).unwrap() + } + assert_eq!(c(0).to_trail_surrogate(), None); + assert_eq!(c(0xE9).to_trail_surrogate(), None); + assert_eq!(c(0xD800).to_trail_surrogate(), None); + assert_eq!(c(0xDBFF).to_trail_surrogate(), None); + assert_eq!(c(0xDC00).to_trail_surrogate(), Some(0xDC00)); + assert_eq!(c(0xDFFF).to_trail_surrogate(), Some(0xDFFF)); + assert_eq!(c(0x1F4A9).to_trail_surrogate(), None); + assert_eq!(c(0x10FFFF).to_trail_surrogate(), None); +} + #[test] fn code_point_from_char() { assert_eq!(CodePoint::from_char('a').to_u32(), 0x61); @@ -70,35 +100,66 @@ fn wtf8buf_from_string() { #[test] fn wtf8buf_from_wide() { - assert_eq!(Wtf8Buf::from_wide(&[]).bytes, b""); - assert_eq!( - Wtf8Buf::from_wide(&[0x61, 0xE9, 0x20, 0xD83D, 0xD83D, 0xDCA9]).bytes, - b"a\xC3\xA9 \xED\xA0\xBD\xF0\x9F\x92\xA9" - ); + let buf = Wtf8Buf::from_wide(&[]); + assert_eq!(buf.bytes, b""); + assert!(buf.is_known_utf8); + + let buf = Wtf8Buf::from_wide(&[0x61, 0xE9, 0x20, 0xD83D, 0xDCA9]); + assert_eq!(buf.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9"); + assert!(buf.is_known_utf8); + + let buf = Wtf8Buf::from_wide(&[0x61, 0xE9, 0x20, 0xD83D, 0xD83D, 0xDCA9]); + assert_eq!(buf.bytes, b"a\xC3\xA9 \xED\xA0\xBD\xF0\x9F\x92\xA9"); + assert!(!buf.is_known_utf8); + + let buf = Wtf8Buf::from_wide(&[0xD800]); + assert_eq!(buf.bytes, b"\xED\xA0\x80"); + assert!(!buf.is_known_utf8); + + let buf = Wtf8Buf::from_wide(&[0xDBFF]); + assert_eq!(buf.bytes, b"\xED\xAF\xBF"); + assert!(!buf.is_known_utf8); + + let buf = Wtf8Buf::from_wide(&[0xDC00]); + assert_eq!(buf.bytes, b"\xED\xB0\x80"); + assert!(!buf.is_known_utf8); + + let buf = Wtf8Buf::from_wide(&[0xDFFF]); + assert_eq!(buf.bytes, b"\xED\xBF\xBF"); + assert!(!buf.is_known_utf8); } #[test] fn wtf8buf_push_str() { let mut string = Wtf8Buf::new(); assert_eq!(string.bytes, b""); + assert!(string.is_known_utf8); + string.push_str("aé 💩"); assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9"); + assert!(string.is_known_utf8); } #[test] fn wtf8buf_push_char() { let mut string = Wtf8Buf::from_str("aé "); assert_eq!(string.bytes, b"a\xC3\xA9 "); + assert!(string.is_known_utf8); + string.push_char('💩'); assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9"); + assert!(string.is_known_utf8); } #[test] fn wtf8buf_push() { let mut string = Wtf8Buf::from_str("aé "); assert_eq!(string.bytes, b"a\xC3\xA9 "); + assert!(string.is_known_utf8); + string.push(CodePoint::from_char('💩')); assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9"); + assert!(string.is_known_utf8); fn c(value: u32) -> CodePoint { CodePoint::from_u32(value).unwrap() @@ -106,37 +167,46 @@ fn wtf8buf_push() { let mut string = Wtf8Buf::new(); string.push(c(0xD83D)); // lead + assert!(!string.is_known_utf8); string.push(c(0xDCA9)); // trail assert_eq!(string.bytes, b"\xF0\x9F\x92\xA9"); // Magic! let mut string = Wtf8Buf::new(); string.push(c(0xD83D)); // lead + assert!(!string.is_known_utf8); string.push(c(0x20)); // not surrogate string.push(c(0xDCA9)); // trail assert_eq!(string.bytes, b"\xED\xA0\xBD \xED\xB2\xA9"); let mut string = Wtf8Buf::new(); string.push(c(0xD800)); // lead + assert!(!string.is_known_utf8); string.push(c(0xDBFF)); // lead assert_eq!(string.bytes, b"\xED\xA0\x80\xED\xAF\xBF"); let mut string = Wtf8Buf::new(); string.push(c(0xD800)); // lead + assert!(!string.is_known_utf8); string.push(c(0xE000)); // not surrogate assert_eq!(string.bytes, b"\xED\xA0\x80\xEE\x80\x80"); let mut string = Wtf8Buf::new(); string.push(c(0xD7FF)); // not surrogate + assert!(string.is_known_utf8); string.push(c(0xDC00)); // trail + assert!(!string.is_known_utf8); assert_eq!(string.bytes, b"\xED\x9F\xBF\xED\xB0\x80"); let mut string = Wtf8Buf::new(); string.push(c(0x61)); // not surrogate, < 3 bytes + assert!(string.is_known_utf8); string.push(c(0xDC00)); // trail + assert!(!string.is_known_utf8); assert_eq!(string.bytes, b"\x61\xED\xB0\x80"); let mut string = Wtf8Buf::new(); string.push(c(0xDC00)); // trail + assert!(!string.is_known_utf8); assert_eq!(string.bytes, b"\xED\xB0\x80"); } @@ -146,6 +216,7 @@ fn wtf8buf_push_wtf8() { assert_eq!(string.bytes, b"a\xC3\xA9"); string.push_wtf8(Wtf8::from_str(" 💩")); assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9"); + assert!(string.is_known_utf8); fn w(v: &[u8]) -> &Wtf8 { unsafe { Wtf8::from_bytes_unchecked(v) } @@ -161,37 +232,68 @@ fn wtf8buf_push_wtf8() { string.push_wtf8(w(b" ")); // not surrogate string.push_wtf8(w(b"\xED\xB2\xA9")); // trail assert_eq!(string.bytes, b"\xED\xA0\xBD \xED\xB2\xA9"); + assert!(!string.is_known_utf8); let mut string = Wtf8Buf::new(); string.push_wtf8(w(b"\xED\xA0\x80")); // lead string.push_wtf8(w(b"\xED\xAF\xBF")); // lead assert_eq!(string.bytes, b"\xED\xA0\x80\xED\xAF\xBF"); + assert!(!string.is_known_utf8); let mut string = Wtf8Buf::new(); string.push_wtf8(w(b"\xED\xA0\x80")); // lead string.push_wtf8(w(b"\xEE\x80\x80")); // not surrogate assert_eq!(string.bytes, b"\xED\xA0\x80\xEE\x80\x80"); + assert!(!string.is_known_utf8); let mut string = Wtf8Buf::new(); string.push_wtf8(w(b"\xED\x9F\xBF")); // not surrogate string.push_wtf8(w(b"\xED\xB0\x80")); // trail assert_eq!(string.bytes, b"\xED\x9F\xBF\xED\xB0\x80"); + assert!(!string.is_known_utf8); let mut string = Wtf8Buf::new(); string.push_wtf8(w(b"a")); // not surrogate, < 3 bytes string.push_wtf8(w(b"\xED\xB0\x80")); // trail assert_eq!(string.bytes, b"\x61\xED\xB0\x80"); + assert!(!string.is_known_utf8); let mut string = Wtf8Buf::new(); string.push_wtf8(w(b"\xED\xB0\x80")); // trail assert_eq!(string.bytes, b"\xED\xB0\x80"); + assert!(!string.is_known_utf8); } #[test] fn wtf8buf_truncate() { let mut string = Wtf8Buf::from_str("aé"); + assert!(string.is_known_utf8); + + string.truncate(3); + assert_eq!(string.bytes, b"a\xC3\xA9"); + assert!(string.is_known_utf8); + string.truncate(1); assert_eq!(string.bytes, b"a"); + assert!(string.is_known_utf8); + + string.truncate(0); + assert_eq!(string.bytes, b""); + assert!(string.is_known_utf8); +} + +#[test] +fn wtf8buf_truncate_around_non_bmp() { + let mut string = Wtf8Buf::from_str("💩"); + assert!(string.is_known_utf8); + + string.truncate(4); + assert_eq!(string.bytes, b"\xF0\x9F\x92\xA9"); + assert!(string.is_known_utf8); + + string.truncate(0); + assert_eq!(string.bytes, b""); + assert!(string.is_known_utf8); } #[test] @@ -208,11 +310,37 @@ fn wtf8buf_truncate_fail_longer() { string.truncate(4); } +#[test] +#[should_panic] +fn wtf8buf_truncate_splitting_non_bmp3() { + let mut string = Wtf8Buf::from_str("💩"); + assert!(string.is_known_utf8); + string.truncate(3); +} + +#[test] +#[should_panic] +fn wtf8buf_truncate_splitting_non_bmp2() { + let mut string = Wtf8Buf::from_str("💩"); + assert!(string.is_known_utf8); + string.truncate(2); +} + +#[test] +#[should_panic] +fn wtf8buf_truncate_splitting_non_bmp1() { + let mut string = Wtf8Buf::from_str("💩"); + assert!(string.is_known_utf8); + string.truncate(1); +} + #[test] fn wtf8buf_into_string() { let mut string = Wtf8Buf::from_str("aé 💩"); + assert!(string.is_known_utf8); assert_eq!(string.clone().into_string(), Ok(String::from("aé 💩"))); string.push(CodePoint::from_u32(0xD800).unwrap()); + assert!(!string.is_known_utf8); assert_eq!(string.clone().into_string(), Err(string)); } @@ -229,15 +357,33 @@ fn wtf8buf_from_iterator() { fn f(values: &[u32]) -> Wtf8Buf { values.iter().map(|&c| CodePoint::from_u32(c).unwrap()).collect::() } - assert_eq!(f(&[0x61, 0xE9, 0x20, 0x1F4A9]).bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9"); + assert_eq!( + f(&[0x61, 0xE9, 0x20, 0x1F4A9]), + Wtf8Buf { bytes: b"a\xC3\xA9 \xF0\x9F\x92\xA9".to_vec(), is_known_utf8: true } + ); assert_eq!(f(&[0xD83D, 0xDCA9]).bytes, b"\xF0\x9F\x92\xA9"); // Magic! - assert_eq!(f(&[0xD83D, 0x20, 0xDCA9]).bytes, b"\xED\xA0\xBD \xED\xB2\xA9"); - assert_eq!(f(&[0xD800, 0xDBFF]).bytes, b"\xED\xA0\x80\xED\xAF\xBF"); - assert_eq!(f(&[0xD800, 0xE000]).bytes, b"\xED\xA0\x80\xEE\x80\x80"); - assert_eq!(f(&[0xD7FF, 0xDC00]).bytes, b"\xED\x9F\xBF\xED\xB0\x80"); - assert_eq!(f(&[0x61, 0xDC00]).bytes, b"\x61\xED\xB0\x80"); - assert_eq!(f(&[0xDC00]).bytes, b"\xED\xB0\x80"); + assert_eq!( + f(&[0xD83D, 0x20, 0xDCA9]), + Wtf8Buf { bytes: b"\xED\xA0\xBD \xED\xB2\xA9".to_vec(), is_known_utf8: false } + ); + assert_eq!( + f(&[0xD800, 0xDBFF]), + Wtf8Buf { bytes: b"\xED\xA0\x80\xED\xAF\xBF".to_vec(), is_known_utf8: false } + ); + assert_eq!( + f(&[0xD800, 0xE000]), + Wtf8Buf { bytes: b"\xED\xA0\x80\xEE\x80\x80".to_vec(), is_known_utf8: false } + ); + assert_eq!( + f(&[0xD7FF, 0xDC00]), + Wtf8Buf { bytes: b"\xED\x9F\xBF\xED\xB0\x80".to_vec(), is_known_utf8: false } + ); + assert_eq!( + f(&[0x61, 0xDC00]), + Wtf8Buf { bytes: b"\x61\xED\xB0\x80".to_vec(), is_known_utf8: false } + ); + assert_eq!(f(&[0xDC00]), Wtf8Buf { bytes: b"\xED\xB0\x80".to_vec(), is_known_utf8: false }); } #[test] @@ -251,15 +397,36 @@ fn wtf8buf_extend() { string } - assert_eq!(e(&[0x61, 0xE9], &[0x20, 0x1F4A9]).bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9"); + assert_eq!( + e(&[0x61, 0xE9], &[0x20, 0x1F4A9]), + Wtf8Buf { bytes: b"a\xC3\xA9 \xF0\x9F\x92\xA9".to_vec(), is_known_utf8: true } + ); assert_eq!(e(&[0xD83D], &[0xDCA9]).bytes, b"\xF0\x9F\x92\xA9"); // Magic! - assert_eq!(e(&[0xD83D, 0x20], &[0xDCA9]).bytes, b"\xED\xA0\xBD \xED\xB2\xA9"); - assert_eq!(e(&[0xD800], &[0xDBFF]).bytes, b"\xED\xA0\x80\xED\xAF\xBF"); - assert_eq!(e(&[0xD800], &[0xE000]).bytes, b"\xED\xA0\x80\xEE\x80\x80"); - assert_eq!(e(&[0xD7FF], &[0xDC00]).bytes, b"\xED\x9F\xBF\xED\xB0\x80"); - assert_eq!(e(&[0x61], &[0xDC00]).bytes, b"\x61\xED\xB0\x80"); - assert_eq!(e(&[], &[0xDC00]).bytes, b"\xED\xB0\x80"); + assert_eq!( + e(&[0xD83D, 0x20], &[0xDCA9]), + Wtf8Buf { bytes: b"\xED\xA0\xBD \xED\xB2\xA9".to_vec(), is_known_utf8: false } + ); + assert_eq!( + e(&[0xD800], &[0xDBFF]), + Wtf8Buf { bytes: b"\xED\xA0\x80\xED\xAF\xBF".to_vec(), is_known_utf8: false } + ); + assert_eq!( + e(&[0xD800], &[0xE000]), + Wtf8Buf { bytes: b"\xED\xA0\x80\xEE\x80\x80".to_vec(), is_known_utf8: false } + ); + assert_eq!( + e(&[0xD7FF], &[0xDC00]), + Wtf8Buf { bytes: b"\xED\x9F\xBF\xED\xB0\x80".to_vec(), is_known_utf8: false } + ); + assert_eq!( + e(&[0x61], &[0xDC00]), + Wtf8Buf { bytes: b"\x61\xED\xB0\x80".to_vec(), is_known_utf8: false } + ); + assert_eq!( + e(&[], &[0xDC00]), + Wtf8Buf { bytes: b"\xED\xB0\x80".to_vec(), is_known_utf8: false } + ); } #[test] @@ -407,3 +574,101 @@ fn wtf8_encode_wide_size_hint() { assert_eq!((0, Some(0)), iter.size_hint()); assert!(iter.next().is_none()); } + +#[test] +fn wtf8_clone_into() { + let mut string = Wtf8Buf::new(); + Wtf8::from_str("green").clone_into(&mut string); + assert_eq!(string.bytes, b"green"); + + let mut string = Wtf8Buf::from_str("green"); + Wtf8::from_str("").clone_into(&mut string); + assert_eq!(string.bytes, b""); + + let mut string = Wtf8Buf::from_str("red"); + Wtf8::from_str("green").clone_into(&mut string); + assert_eq!(string.bytes, b"green"); + + let mut string = Wtf8Buf::from_str("green"); + Wtf8::from_str("red").clone_into(&mut string); + assert_eq!(string.bytes, b"red"); + + let mut string = Wtf8Buf::from_str("green"); + assert!(string.is_known_utf8); + unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").clone_into(&mut string) }; + assert_eq!(string.bytes, b"\xED\xA0\x80"); + assert!(!string.is_known_utf8); +} + +#[test] +fn wtf8_to_ascii_lowercase() { + let lowercase = Wtf8::from_str("").to_ascii_lowercase(); + assert_eq!(lowercase.bytes, b""); + assert!(lowercase.is_known_utf8); + + let lowercase = Wtf8::from_str("GrEeN gRaPeS! 🍇").to_ascii_lowercase(); + assert_eq!(lowercase.bytes, b"green grapes! \xf0\x9f\x8d\x87"); + assert!(lowercase.is_known_utf8); + + let lowercase = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_ascii_lowercase() }; + assert_eq!(lowercase.bytes, b"\xED\xA0\x80"); + assert!(!lowercase.is_known_utf8); +} + +#[test] +fn wtf8_to_ascii_uppercase() { + let uppercase = Wtf8::from_str("").to_ascii_uppercase(); + assert_eq!(uppercase.bytes, b""); + assert!(uppercase.is_known_utf8); + + let uppercase = Wtf8::from_str("GrEeN gRaPeS! 🍇").to_ascii_uppercase(); + assert_eq!(uppercase.bytes, b"GREEN GRAPES! \xf0\x9f\x8d\x87"); + assert!(uppercase.is_known_utf8); + + let uppercase = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_ascii_uppercase() }; + assert_eq!(uppercase.bytes, b"\xED\xA0\x80"); + assert!(!uppercase.is_known_utf8); +} + +#[test] +fn wtf8_make_ascii_lowercase() { + let mut lowercase = Wtf8Buf::from_str(""); + lowercase.make_ascii_lowercase(); + assert_eq!(lowercase.bytes, b""); + assert!(lowercase.is_known_utf8); + + let mut lowercase = Wtf8Buf::from_str("GrEeN gRaPeS! 🍇"); + lowercase.make_ascii_lowercase(); + assert_eq!(lowercase.bytes, b"green grapes! \xf0\x9f\x8d\x87"); + assert!(lowercase.is_known_utf8); + + let mut lowercase = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() }; + lowercase.make_ascii_lowercase(); + assert_eq!(lowercase.bytes, b"\xED\xA0\x80"); + assert!(!lowercase.is_known_utf8); +} + +#[test] +fn wtf8_make_ascii_uppercase() { + let mut uppercase = Wtf8Buf::from_str(""); + uppercase.make_ascii_uppercase(); + assert_eq!(uppercase.bytes, b""); + assert!(uppercase.is_known_utf8); + + let mut uppercase = Wtf8Buf::from_str("GrEeN gRaPeS! 🍇"); + uppercase.make_ascii_uppercase(); + assert_eq!(uppercase.bytes, b"GREEN GRAPES! \xf0\x9f\x8d\x87"); + assert!(uppercase.is_known_utf8); + + let mut uppercase = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() }; + uppercase.make_ascii_uppercase(); + assert_eq!(uppercase.bytes, b"\xED\xA0\x80"); + assert!(!uppercase.is_known_utf8); +} + +#[test] +fn wtf8_to_owned() { + let string = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() }; + assert_eq!(string.bytes, b"\xED\xA0\x80"); + assert!(!string.is_known_utf8); +} -- cgit 1.4.1-3-g733a5 From d3a585e593f441405fd30d082b8eb70e0b4c0d62 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 9 May 2022 08:55:06 -0700 Subject: Panic safety. --- library/std/src/sys_common/wtf8.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs index a674ced88bb..718308d1e2a 100644 --- a/library/std/src/sys_common/wtf8.rs +++ b/library/std/src/sys_common/wtf8.rs @@ -220,11 +220,11 @@ impl Wtf8Buf { let surrogate = surrogate.unpaired_surrogate(); // Surrogates are known to be in the code point range. let code_point = unsafe { CodePoint::from_u32_unchecked(surrogate as u32) }; + // The string will now contain an unpaired surrogate. + string.is_known_utf8 = false; // Skip the WTF-8 concatenation check, // surrogate pairs are already decoded by decode_utf16 string.push_code_point_unchecked(code_point); - // The string now contains an unpaired surrogate. - string.is_known_utf8 = false; } } } @@ -346,13 +346,13 @@ impl Wtf8Buf { self.bytes.extend_from_slice(other_without_trail_surrogate); } _ => { - self.bytes.extend_from_slice(&other.bytes); - - // If we're pushing a string containing a surrogate, we may no - // longer have UTF-8. + // If we'll be pushing a string containing a surrogate, we may + // no longer have UTF-8. if other.next_surrogate(0).is_some() { self.is_known_utf8 = false; } + + self.bytes.extend_from_slice(&other.bytes); } } } @@ -721,8 +721,8 @@ impl Wtf8 { } pub fn clone_into(&self, buf: &mut Wtf8Buf) { - self.bytes.clone_into(&mut buf.bytes); buf.is_known_utf8 = false; + self.bytes.clone_into(&mut buf.bytes); } /// Boxes this `Wtf8`. -- cgit 1.4.1-3-g733a5 From a7d57c61c2422b7942575936faf9a62d9e5e1599 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 9 May 2022 09:06:27 -0700 Subject: Don't eagerly scan for `is_known_utf8` in `to_ascii_lowercase`/`uppercase`. --- library/std/src/sys_common/wtf8.rs | 10 ++-------- library/std/src/sys_common/wtf8/tests.rs | 4 ---- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs index 718308d1e2a..86d173d8fcd 100644 --- a/library/std/src/sys_common/wtf8.rs +++ b/library/std/src/sys_common/wtf8.rs @@ -762,18 +762,12 @@ impl Wtf8 { #[inline] pub fn to_ascii_lowercase(&self) -> Wtf8Buf { - Wtf8Buf { - bytes: self.bytes.to_ascii_lowercase(), - is_known_utf8: self.next_surrogate(0).is_none(), - } + Wtf8Buf { bytes: self.bytes.to_ascii_lowercase(), is_known_utf8: false } } #[inline] pub fn to_ascii_uppercase(&self) -> Wtf8Buf { - Wtf8Buf { - bytes: self.bytes.to_ascii_uppercase(), - is_known_utf8: self.next_surrogate(0).is_none(), - } + Wtf8Buf { bytes: self.bytes.to_ascii_uppercase(), is_known_utf8: false } } #[inline] diff --git a/library/std/src/sys_common/wtf8/tests.rs b/library/std/src/sys_common/wtf8/tests.rs index 8360e3da215..ba2bdc76e3b 100644 --- a/library/std/src/sys_common/wtf8/tests.rs +++ b/library/std/src/sys_common/wtf8/tests.rs @@ -635,12 +635,10 @@ fn wtf8_make_ascii_lowercase() { let mut lowercase = Wtf8Buf::from_str(""); lowercase.make_ascii_lowercase(); assert_eq!(lowercase.bytes, b""); - assert!(lowercase.is_known_utf8); let mut lowercase = Wtf8Buf::from_str("GrEeN gRaPeS! 🍇"); lowercase.make_ascii_lowercase(); assert_eq!(lowercase.bytes, b"green grapes! \xf0\x9f\x8d\x87"); - assert!(lowercase.is_known_utf8); let mut lowercase = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() }; lowercase.make_ascii_lowercase(); @@ -653,12 +651,10 @@ fn wtf8_make_ascii_uppercase() { let mut uppercase = Wtf8Buf::from_str(""); uppercase.make_ascii_uppercase(); assert_eq!(uppercase.bytes, b""); - assert!(uppercase.is_known_utf8); let mut uppercase = Wtf8Buf::from_str("GrEeN gRaPeS! 🍇"); uppercase.make_ascii_uppercase(); assert_eq!(uppercase.bytes, b"GREEN GRAPES! \xf0\x9f\x8d\x87"); - assert!(uppercase.is_known_utf8); let mut uppercase = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() }; uppercase.make_ascii_uppercase(); -- cgit 1.4.1-3-g733a5 From 516a67aad9a2d962917724138654e8f14a0fac4c Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 9 May 2022 09:32:09 -0700 Subject: Remove `is_known_utf8` checks from more tests where it's no longer set. --- library/std/src/sys_common/wtf8/tests.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/library/std/src/sys_common/wtf8/tests.rs b/library/std/src/sys_common/wtf8/tests.rs index ba2bdc76e3b..1a302d64694 100644 --- a/library/std/src/sys_common/wtf8/tests.rs +++ b/library/std/src/sys_common/wtf8/tests.rs @@ -604,11 +604,9 @@ fn wtf8_clone_into() { fn wtf8_to_ascii_lowercase() { let lowercase = Wtf8::from_str("").to_ascii_lowercase(); assert_eq!(lowercase.bytes, b""); - assert!(lowercase.is_known_utf8); let lowercase = Wtf8::from_str("GrEeN gRaPeS! 🍇").to_ascii_lowercase(); assert_eq!(lowercase.bytes, b"green grapes! \xf0\x9f\x8d\x87"); - assert!(lowercase.is_known_utf8); let lowercase = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_ascii_lowercase() }; assert_eq!(lowercase.bytes, b"\xED\xA0\x80"); @@ -619,11 +617,9 @@ fn wtf8_to_ascii_lowercase() { fn wtf8_to_ascii_uppercase() { let uppercase = Wtf8::from_str("").to_ascii_uppercase(); assert_eq!(uppercase.bytes, b""); - assert!(uppercase.is_known_utf8); let uppercase = Wtf8::from_str("GrEeN gRaPeS! 🍇").to_ascii_uppercase(); assert_eq!(uppercase.bytes, b"GREEN GRAPES! \xf0\x9f\x8d\x87"); - assert!(uppercase.is_known_utf8); let uppercase = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_ascii_uppercase() }; assert_eq!(uppercase.bytes, b"\xED\xA0\x80"); -- cgit 1.4.1-3-g733a5 From ddeb936c6d797d47ec8652c885c8a2cceba8386f Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 17 May 2022 18:23:43 -0700 Subject: Don't test the rustdoc rendering context size on Windows. This assert is just making sure the size of `Context` doens't grow unexpectedly, and it's already not being checked on every platform. `PathBuf` now has a different size on Windows, so adjust this to avoid checking the size on Windows. --- src/librustdoc/html/render/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index bfdc44c7e45..367ffd4e883 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -71,7 +71,7 @@ pub(crate) struct Context<'tcx> { } // `Context` is cloned a lot, so we don't want the size to grow unexpectedly. -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +#[cfg(all(not(windows), target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(Context<'_>, 128); /// Shared mutable state used in [`Context`] and elsewhere. -- cgit 1.4.1-3-g733a5 From 661d488bfd7cd4888400a23b9f6ea9bb15cacaf5 Mon Sep 17 00:00:00 2001 From: ouz-a Date: Fri, 24 Jun 2022 14:16:48 +0300 Subject: use true recursion --- .../rustc_mir_build/src/thir/pattern/usefulness.rs | 33 +++++++++++++--------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index 5bb2f00d3cf..5773ba8065c 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -364,8 +364,8 @@ impl<'a, 'p, 'tcx> fmt::Debug for PatCtxt<'a, 'p, 'tcx> { /// A row of a matrix. Rows of len 1 are very common, which is why `SmallVec[_; 2]` /// works well. #[derive(Clone)] -struct PatStack<'p, 'tcx> { - pats: SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]>, +pub(crate) struct PatStack<'p, 'tcx> { + pub(crate) pats: SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]>, } impl<'p, 'tcx> PatStack<'p, 'tcx> { @@ -403,6 +403,21 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> { }) } + // Recursively expand all patterns into their subpatterns and push each `PatStack` to matrix. + fn expand_and_extend<'a>(&'a self, matrix: &mut Matrix<'p, 'tcx>) { + if !self.is_empty() && self.head().is_or_pat() { + for pat in self.head().iter_fields() { + let mut new_patstack = PatStack::from_pattern(pat); + new_patstack.pats.extend_from_slice(&self.pats[1..]); + if !new_patstack.is_empty() && new_patstack.head().is_or_pat() { + new_patstack.expand_and_extend(matrix); + } else if !new_patstack.is_empty() { + matrix.push(new_patstack); + } + } + } + } + /// This computes `S(self.head().ctor(), self)`. See top of the file for explanations. /// /// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing @@ -436,7 +451,7 @@ impl<'p, 'tcx> fmt::Debug for PatStack<'p, 'tcx> { /// A 2D matrix. #[derive(Clone)] pub(super) struct Matrix<'p, 'tcx> { - patterns: Vec>, + pub patterns: Vec>, } impl<'p, 'tcx> Matrix<'p, 'tcx> { @@ -453,17 +468,7 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> { /// expands it. fn push(&mut self, row: PatStack<'p, 'tcx>) { if !row.is_empty() && row.head().is_or_pat() { - let pats = row.expand_or_pat(); - let mut no_inner_or = true; - for pat in pats { - if !pat.is_empty() && pat.head().is_or_pat() { - self.patterns.extend(pat.expand_or_pat()); - no_inner_or = false; - } - } - if no_inner_or { - self.patterns.extend(row.expand_or_pat()); - } + row.expand_and_extend(self); } else { self.patterns.push(row); } -- cgit 1.4.1-3-g733a5 From 14d288fe125813b130a6571bbf2ae49c5f247174 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 23 Apr 2022 11:05:31 +0100 Subject: socket `set_mark` addition. to be able to set a marker/id on the socket for network filtering (iptables/ipfw here) purpose. --- library/std/src/os/unix/net/stream.rs | 6 ++++++ library/std/src/sys/unix/net.rs | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index 1d6083e66e1..7eb06be3e09 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -424,6 +424,12 @@ impl UnixStream { self.0.passcred() } + #[cfg(any(doc, target_os = "linux", target_os = "freebsd",))] + #[unstable(feature = "unix_set_mark", issue = "none")] + pub fn set_mark(&self, mark: u32) -> io::Result<()> { + self.0.set_mark(mark) + } + /// Returns the value of the `SO_ERROR` option. /// /// # Examples diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index a1bbc2d87b6..60ee52528c5 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -427,6 +427,16 @@ impl Socket { self.0.set_nonblocking(nonblocking) } + #[cfg(target_os = "linux")] + pub fn set_mark(&self, mark: u32) -> io::Result<()> { + setsockopt(self, libc::SOL_SOCKET, libc::SO_MARK, mark as libc::c_int) + } + + #[cfg(target_os = "freebsd")] + pub fn set_mark(&self, mark: u32) -> io::Result<()> { + setsockopt(self, libc::SOL_SOCKET, libc::SO_USER_COOKIE, mark) + } + pub fn take_error(&self) -> io::Result> { let raw: c_int = getsockopt(self, libc::SOL_SOCKET, libc::SO_ERROR)?; if raw == 0 { Ok(None) } else { Ok(Some(io::Error::from_raw_os_error(raw as i32))) } -- cgit 1.4.1-3-g733a5 From 48ef00e36f58c1debaec8d5612297b8819f7a690 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 27 Apr 2022 06:01:05 +0100 Subject: doc additions --- library/std/src/os/unix/net/datagram.rs | 19 +++++++++++++++++++ library/std/src/os/unix/net/stream.rs | 15 ++++++++++++++- library/std/src/sys/unix/net.rs | 5 +++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index 8008acfd1c9..7f5d760481b 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -838,6 +838,25 @@ impl UnixDatagram { self.0.passcred() } + /// Set the id of the socket for network filtering purpose + /// and is only a setter. + /// + /// ```no_run + /// #![feature(unix_set_mark)] + /// use std::os::unix::net::UnixDatagram; + /// + /// fn main() -> std::io::Result<()> { + /// let sock = UnixDatagram::unbound()?; + /// sock.set_mark(32 as u32).expect("set_mark function failed"); + /// Ok(()) + /// } + /// ``` + #[cfg(any(doc, target_os = "linux", target_os = "freebsd", target_os = "openbsd",))] + #[unstable(feature = "unix_set_mark", issue = "none")] + pub fn set_mark(&self, mark: u32) -> io::Result<()> { + self.0.set_mark(mark) + } + /// Returns the value of the `SO_ERROR` option. /// /// # Examples diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index 7eb06be3e09..7ecb81340ac 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -424,7 +424,20 @@ impl UnixStream { self.0.passcred() } - #[cfg(any(doc, target_os = "linux", target_os = "freebsd",))] + /// Set the id of the socket for network filtering purpose + /// and is only a setter. + /// + /// ```no_run + /// #![feature(unix_set_mark)] + /// use std::os::unix::net::UnixStream; + /// + /// fn main() -> std::io::Result<()> { + /// let sock = UnixStream::connect("/tmp/sock")?; + /// sock.set_mark(32 as u32).expect("set_mark function failed"); + /// Ok(()) + /// } + /// ``` + #[cfg(any(doc, target_os = "linux", target_os = "freebsd", target_os = "openbsd",))] #[unstable(feature = "unix_set_mark", issue = "none")] pub fn set_mark(&self, mark: u32) -> io::Result<()> { self.0.set_mark(mark) diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index 60ee52528c5..30667edafba 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -437,6 +437,11 @@ impl Socket { setsockopt(self, libc::SOL_SOCKET, libc::SO_USER_COOKIE, mark) } + #[cfg(target_os = "openbsd")] + pub fn set_mark(&self, mark: u32) -> io::Result<()> { + setsockopt(self, libc::SOL_SOCKET, libc::SO_RTABLE, mark as libc::c_int) + } + pub fn take_error(&self) -> io::Result> { let raw: c_int = getsockopt(self, libc::SOL_SOCKET, libc::SO_ERROR)?; if raw == 0 { Ok(None) } else { Ok(Some(io::Error::from_raw_os_error(raw as i32))) } -- cgit 1.4.1-3-g733a5 From 10f5a19a4deac4a7300ed6bfad11731d451713b0 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 6 Jul 2022 20:01:25 +0100 Subject: changes from feedback --- library/std/src/os/unix/net/datagram.rs | 5 ++--- library/std/src/os/unix/net/stream.rs | 5 ++--- library/std/src/sys/unix/net.rs | 20 ++++++++------------ 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index 7f5d760481b..02d0f24cd65 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -839,7 +839,6 @@ impl UnixDatagram { } /// Set the id of the socket for network filtering purpose - /// and is only a setter. /// /// ```no_run /// #![feature(unix_set_mark)] @@ -847,12 +846,12 @@ impl UnixDatagram { /// /// fn main() -> std::io::Result<()> { /// let sock = UnixDatagram::unbound()?; - /// sock.set_mark(32 as u32).expect("set_mark function failed"); + /// sock.set_mark(32)?; /// Ok(()) /// } /// ``` #[cfg(any(doc, target_os = "linux", target_os = "freebsd", target_os = "openbsd",))] - #[unstable(feature = "unix_set_mark", issue = "none")] + #[unstable(feature = "unix_set_mark", issue = "96467")] pub fn set_mark(&self, mark: u32) -> io::Result<()> { self.0.set_mark(mark) } diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index 7ecb81340ac..ece0f91dad0 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -425,7 +425,6 @@ impl UnixStream { } /// Set the id of the socket for network filtering purpose - /// and is only a setter. /// /// ```no_run /// #![feature(unix_set_mark)] @@ -433,12 +432,12 @@ impl UnixStream { /// /// fn main() -> std::io::Result<()> { /// let sock = UnixStream::connect("/tmp/sock")?; - /// sock.set_mark(32 as u32).expect("set_mark function failed"); + /// sock.set_mark(32)?; /// Ok(()) /// } /// ``` #[cfg(any(doc, target_os = "linux", target_os = "freebsd", target_os = "openbsd",))] - #[unstable(feature = "unix_set_mark", issue = "none")] + #[unstable(feature = "unix_set_mark", issue = "96467")] pub fn set_mark(&self, mark: u32) -> io::Result<()> { self.0.set_mark(mark) } diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index 30667edafba..c942689eddf 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -427,19 +427,15 @@ impl Socket { self.0.set_nonblocking(nonblocking) } - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd"))] pub fn set_mark(&self, mark: u32) -> io::Result<()> { - setsockopt(self, libc::SOL_SOCKET, libc::SO_MARK, mark as libc::c_int) - } - - #[cfg(target_os = "freebsd")] - pub fn set_mark(&self, mark: u32) -> io::Result<()> { - setsockopt(self, libc::SOL_SOCKET, libc::SO_USER_COOKIE, mark) - } - - #[cfg(target_os = "openbsd")] - pub fn set_mark(&self, mark: u32) -> io::Result<()> { - setsockopt(self, libc::SOL_SOCKET, libc::SO_RTABLE, mark as libc::c_int) + #[cfg(target_os = "linux")] + let option = libc::SO_MARK; + #[cfg(target_os = "freebsd")] + let option = libc::SO_USER_COOKIE; + #[cfg(target_os = "openbsd")] + let option = libc::SO_RTABLE; + setsockopt(self, libc::SOL_SOCKET, option, mark as libc::c_int) } pub fn take_error(&self) -> io::Result> { -- cgit 1.4.1-3-g733a5 From f6efb0b74f286dc806b2fb46b3bd880606533c64 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Thu, 7 Jul 2022 13:45:05 +0100 Subject: Fix doc build on unsupported oses --- library/std/src/os/unix/net/datagram.rs | 9 ++++++++- library/std/src/os/unix/net/stream.rs | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index 02d0f24cd65..f758f88d0a3 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -840,7 +840,14 @@ impl UnixDatagram { /// Set the id of the socket for network filtering purpose /// - /// ```no_run + #[cfg_attr( + any(target_os = "linux", target_os = "freebsd", target_os = "openbsd"), + doc = "```no_run" + )] + #[cfg_attr( + not(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd")), + doc = "```ignore" + )] /// #![feature(unix_set_mark)] /// use std::os::unix::net::UnixDatagram; /// diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index ece0f91dad0..240c5a77105 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -426,7 +426,14 @@ impl UnixStream { /// Set the id of the socket for network filtering purpose /// - /// ```no_run + #[cfg_attr( + any(target_os = "linux", target_os = "freebsd", target_os = "openbsd"), + doc = "```no_run" + )] + #[cfg_attr( + not(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd")), + doc = "```ignore" + )] /// #![feature(unix_set_mark)] /// use std::os::unix::net::UnixStream; /// -- cgit 1.4.1-3-g733a5 From 54d35e71a6a0053641e5813f74fbcf1c7379503a Mon Sep 17 00:00:00 2001 From: Yiming Lei Date: Fri, 8 Jul 2022 12:42:29 -0700 Subject: distinguish the method and associated function diagnostic information Methods are defined within the context of a struct and their first parameter is always self Associated functions don’t take self as a parameter modified: compiler/rustc_typeck/src/check/method/suggest.rs modified: src/test/ui/auto-ref-slice-plus-ref.stderr modified: src/test/ui/block-result/issue-3563.stderr modified: src/test/ui/issues/issue-28344.stderr modified: src/test/ui/suggestions/dont-suggest-pin-array-dot-set.stderr modified: src/test/ui/suggestions/suggest-methods.stderr modified: src/test/ui/traits/trait-upcasting/subtrait-method.stderr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compiler/rustc_typeck/src/check/method/suggest.rs | 33 +++++++++++++++------- src/test/ui/auto-ref-slice-plus-ref.stderr | 2 +- src/test/ui/block-result/issue-3563.stderr | 2 +- src/test/ui/issues/issue-28344.stderr | 4 +-- .../dont-suggest-pin-array-dot-set.stderr | 2 +- src/test/ui/suggestions/suggest-methods.stderr | 8 +++--- .../traits/trait-upcasting/subtrait-method.stderr | 10 +++---- 7 files changed, 37 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 4e1a105fc71..4b910493558 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -1035,16 +1035,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // that had unsatisfied trait bounds if unsatisfied_predicates.is_empty() { let def_kind = lev_candidate.kind.as_def_kind(); - err.span_suggestion( - span, - &format!( - "there is {} {} with a similar name", - def_kind.article(), - def_kind.descr(lev_candidate.def_id), - ), - lev_candidate.name, - Applicability::MaybeIncorrect, - ); + // Methods are defined within the context of a struct and their first parameter is always self, + // which represents the instance of the struct the method is being called on + // Associated functions don’t take self as a parameter and + // they are not methods because they don’t have an instance of the struct to work with. + if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter { + err.span_suggestion( + span, + &format!("there is a method with a similar name",), + lev_candidate.name, + Applicability::MaybeIncorrect, + ); + } else { + err.span_suggestion( + span, + &format!( + "there is {} {} with a similar name", + def_kind.article(), + def_kind.descr(lev_candidate.def_id), + ), + lev_candidate.name, + Applicability::MaybeIncorrect, + ); + } } } diff --git a/src/test/ui/auto-ref-slice-plus-ref.stderr b/src/test/ui/auto-ref-slice-plus-ref.stderr index eb8447ff0f3..e2883050720 100644 --- a/src/test/ui/auto-ref-slice-plus-ref.stderr +++ b/src/test/ui/auto-ref-slice-plus-ref.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `test_mut` found for struct `Vec<{integer}>` in th --> $DIR/auto-ref-slice-plus-ref.rs:7:7 | LL | a.test_mut(); - | ^^^^^^^^ help: there is an associated function with a similar name: `get_mut` + | ^^^^^^^^ help: there is a method with a similar name: `get_mut` | = help: items from traits can only be used if the trait is implemented and in scope note: `MyIter` defines an item `test_mut`, perhaps you need to implement it diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr index 5255e48bee1..be551f6e889 100644 --- a/src/test/ui/block-result/issue-3563.stderr +++ b/src/test/ui/block-result/issue-3563.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `b` found for reference `&Self` in the current sco --> $DIR/issue-3563.rs:3:17 | LL | || self.b() - | ^ help: there is an associated function with a similar name: `a` + | ^ help: there is a method with a similar name: `a` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-28344.stderr b/src/test/ui/issues/issue-28344.stderr index b1d1c01b27a..85a8698afc5 100644 --- a/src/test/ui/issues/issue-28344.stderr +++ b/src/test/ui/issues/issue-28344.stderr @@ -25,7 +25,7 @@ LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8); | ^^^^^ | | | function or associated item not found in `dyn BitXor<_>` - | help: there is an associated function with a similar name: `bitxor` + | help: there is a method with a similar name: `bitxor` warning: trait objects without an explicit `dyn` are deprecated --> $DIR/issue-28344.rs:10:13 @@ -53,7 +53,7 @@ LL | let g = BitXor::bitor; | ^^^^^ | | | function or associated item not found in `dyn BitXor<_>` - | help: there is an associated function with a similar name: `bitxor` + | help: there is a method with a similar name: `bitxor` error: aborting due to 4 previous errors; 2 warnings emitted diff --git a/src/test/ui/suggestions/dont-suggest-pin-array-dot-set.stderr b/src/test/ui/suggestions/dont-suggest-pin-array-dot-set.stderr index 677aa031bf7..c66da3ea6d9 100644 --- a/src/test/ui/suggestions/dont-suggest-pin-array-dot-set.stderr +++ b/src/test/ui/suggestions/dont-suggest-pin-array-dot-set.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `set` found for array `[u8; 1]` in the current sco --> $DIR/dont-suggest-pin-array-dot-set.rs:14:7 | LL | a.set(0, 3); - | ^^^ help: there is an associated function with a similar name: `get` + | ^^^ help: there is a method with a similar name: `get` error: aborting due to previous error diff --git a/src/test/ui/suggestions/suggest-methods.stderr b/src/test/ui/suggestions/suggest-methods.stderr index dd9010e3295..4277b23fdc1 100644 --- a/src/test/ui/suggestions/suggest-methods.stderr +++ b/src/test/ui/suggestions/suggest-methods.stderr @@ -5,25 +5,25 @@ LL | struct Foo; | --- method `bat` not found for this struct ... LL | f.bat(1.0); - | ^^^ help: there is an associated function with a similar name: `bar` + | ^^^ help: there is a method with a similar name: `bar` error[E0599]: no method named `is_emtpy` found for struct `String` in the current scope --> $DIR/suggest-methods.rs:21:15 | LL | let _ = s.is_emtpy(); - | ^^^^^^^^ help: there is an associated function with a similar name: `is_empty` + | ^^^^^^^^ help: there is a method with a similar name: `is_empty` error[E0599]: no method named `count_eos` found for type `u32` in the current scope --> $DIR/suggest-methods.rs:25:19 | LL | let _ = 63u32.count_eos(); - | ^^^^^^^^^ help: there is an associated function with a similar name: `count_zeros` + | ^^^^^^^^^ help: there is a method with a similar name: `count_zeros` error[E0599]: no method named `count_o` found for type `u32` in the current scope --> $DIR/suggest-methods.rs:28:19 | LL | let _ = 63u32.count_o(); - | ^^^^^^^ help: there is an associated function with a similar name: `count_ones` + | ^^^^^^^ help: there is a method with a similar name: `count_ones` error: aborting due to 4 previous errors diff --git a/src/test/ui/traits/trait-upcasting/subtrait-method.stderr b/src/test/ui/traits/trait-upcasting/subtrait-method.stderr index 8c69011800b..af7a410f6d9 100644 --- a/src/test/ui/traits/trait-upcasting/subtrait-method.stderr +++ b/src/test/ui/traits/trait-upcasting/subtrait-method.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `c` found for reference `&dyn Bar` in the current --> $DIR/subtrait-method.rs:56:9 | LL | bar.c(); - | ^ help: there is an associated function with a similar name: `a` + | ^ help: there is a method with a similar name: `a` | = help: items from traits can only be used if the trait is implemented and in scope note: `Baz` defines an item `c`, perhaps you need to implement it @@ -15,7 +15,7 @@ error[E0599]: no method named `b` found for reference `&dyn Foo` in the current --> $DIR/subtrait-method.rs:60:9 | LL | foo.b(); - | ^ help: there is an associated function with a similar name: `a` + | ^ help: there is a method with a similar name: `a` | = help: items from traits can only be used if the trait is implemented and in scope note: `Bar` defines an item `b`, perhaps you need to implement it @@ -28,7 +28,7 @@ error[E0599]: no method named `c` found for reference `&dyn Foo` in the current --> $DIR/subtrait-method.rs:62:9 | LL | foo.c(); - | ^ help: there is an associated function with a similar name: `a` + | ^ help: there is a method with a similar name: `a` | = help: items from traits can only be used if the trait is implemented and in scope note: `Baz` defines an item `c`, perhaps you need to implement it @@ -41,7 +41,7 @@ error[E0599]: no method named `b` found for reference `&dyn Foo` in the current --> $DIR/subtrait-method.rs:66:9 | LL | foo.b(); - | ^ help: there is an associated function with a similar name: `a` + | ^ help: there is a method with a similar name: `a` | = help: items from traits can only be used if the trait is implemented and in scope note: `Bar` defines an item `b`, perhaps you need to implement it @@ -54,7 +54,7 @@ error[E0599]: no method named `c` found for reference `&dyn Foo` in the current --> $DIR/subtrait-method.rs:68:9 | LL | foo.c(); - | ^ help: there is an associated function with a similar name: `a` + | ^ help: there is a method with a similar name: `a` | = help: items from traits can only be used if the trait is implemented and in scope note: `Baz` defines an item `c`, perhaps you need to implement it -- cgit 1.4.1-3-g733a5 From e540425a2425819be4717ff0e4217c40cc52c99f Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Fri, 1 Jul 2022 23:30:47 -0700 Subject: Add a `File::create_new` constructor We have `File::create` for creating a file or opening an existing file, but the secure way to guarantee creating a new file requires a longhand invocation via `OpenOptions`. Add `File::create_new` to handle this case, to make it easier for people to do secure file creation. --- library/std/src/fs.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index f46997b807a..97093ffb46f 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -366,6 +366,35 @@ impl File { OpenOptions::new().write(true).create(true).truncate(true).open(path.as_ref()) } + /// Creates a new file in read-write mode; error if the file exists. + /// + /// This function will create a file if it does not exist, or return an error if it does. This + /// way, if the call succeeds, the file returned is guaranteed to be new. + /// + /// This option is useful because it is atomic. Otherwise between checking whether a file + /// exists and creating a new one, the file may have been created by another process (a TOCTOU + /// race condition / attack). + /// + /// This can also be written using + /// `File::options().read(true).write(true).create_new(true).open(...)`. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(file_create_new)] + /// + /// use std::fs::File; + /// + /// fn main() -> std::io::Result<()> { + /// let mut f = File::create_new("foo.txt")?; + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "file_create_new", issue = "none")] + pub fn create_new>(path: P) -> io::Result { + OpenOptions::new().read(true).write(true).create_new(true).open(path.as_ref()) + } + /// Returns a new OpenOptions object. /// /// This function returns a new OpenOptions object that you can use to -- cgit 1.4.1-3-g733a5 From 85a9c741588aaf296ce94f480e342c2bf5c131ba Mon Sep 17 00:00:00 2001 From: AngelicosPhosphoros Date: Sun, 17 Jul 2022 23:33:29 +0300 Subject: Add tests that check `Vec::retain` predicate execution order. --- library/alloc/tests/vec.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 5520f6ebf19..b17f7a8eebc 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -292,6 +292,22 @@ fn test_retain() { assert_eq!(vec, [2, 4]); } +#[test] +fn test_retain_predicate_order() { + for to_keep in [true, false] { + let mut number_of_executions = 0; + let mut vec = vec![1, 2, 3, 4]; + let mut next_expected = 1; + vec.retain(|&x| { + assert_eq!(next_expected, x); + next_expected += 1; + number_of_executions += 1; + to_keep + }); + assert_eq!(number_of_executions, 4); + } +} + #[test] fn test_retain_pred_panic_with_hole() { let v = (0..5).map(Rc::new).collect::>(); @@ -353,6 +369,35 @@ fn test_retain_drop_panic() { assert!(v.iter().all(|r| Rc::strong_count(r) == 1)); } +#[test] +fn test_retain_maybeuninits() { + // This test aimed to be run under miri. + use core::mem::MaybeUninit; + let mut vec: Vec<_> = [1i32, 2, 3, 4].map(|v| MaybeUninit::new(vec![v])).into(); + vec.retain(|x| { + // SAFETY: Retain must visit every element of Vec in original order and exactly once. + // Our values is initialized at creation of Vec. + let v = unsafe { x.assume_init_ref()[0] }; + if v & 1 == 0 { + return true; + } + // SAFETY: Value is initialized. + // Value wouldn't be dropped by `Vec::retain` + // because `MaybeUninit` doesn't drop content. + drop(unsafe { x.assume_init_read() }); + false + }); + let vec: Vec = vec + .into_iter() + .map(|x| unsafe { + // SAFETY: All values dropped in retain predicate must be removed by `Vec::retain`. + // Remaining values are initialized. + x.assume_init()[0] + }) + .collect(); + assert_eq!(vec, [2, 4]); +} + #[test] fn test_dedup() { fn case(a: Vec, b: Vec) { -- cgit 1.4.1-3-g733a5 From f74d5c1c72dfd9e5bc8685c56e6a11e5649a89eb Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Mon, 18 Jul 2022 12:05:14 +0200 Subject: add basic REUSE scaffolding --- .reuse/dep5 | 7 +++++++ LICENSES/LicenseRef-TODO.txt | 2 ++ 2 files changed, 9 insertions(+) create mode 100644 .reuse/dep5 create mode 100644 LICENSES/LicenseRef-TODO.txt diff --git a/.reuse/dep5 b/.reuse/dep5 new file mode 100644 index 00000000000..03d9f152d5f --- /dev/null +++ b/.reuse/dep5 @@ -0,0 +1,7 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ + +# Temporarily mark all files to be licensed with the custom "TODO" license, +# until we import the proper licensing metadata in a separate PR. +Files: * +Copyright: TODO +License: LicenseRef-TODO diff --git a/LICENSES/LicenseRef-TODO.txt b/LICENSES/LicenseRef-TODO.txt new file mode 100644 index 00000000000..7b193bf7d5e --- /dev/null +++ b/LICENSES/LicenseRef-TODO.txt @@ -0,0 +1,2 @@ +Temporary placeholder, only needed until we import the actual licensing +metadata. -- cgit 1.4.1-3-g733a5 From 9369e6032e77fd36d426434715a5ed9af2e308d4 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Mon, 18 Jul 2022 12:31:50 +0200 Subject: check REUSE compliance in CI --- src/ci/docker/host-x86_64/mingw-check/Dockerfile | 9 ++ .../host-x86_64/mingw-check/reuse-requirements.in | 22 ++++ .../host-x86_64/mingw-check/reuse-requirements.txt | 145 +++++++++++++++++++++ 3 files changed, 176 insertions(+) create mode 100644 src/ci/docker/host-x86_64/mingw-check/reuse-requirements.in create mode 100644 src/ci/docker/host-x86_64/mingw-check/reuse-requirements.txt diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index 9ee84f420b9..c6723d91c8b 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -1,4 +1,7 @@ FROM ubuntu:18.04 +# FIXME: when bumping the version, remove the Python 3.6-specific changes in +# the reuse-requirements.in file, regenerate reuse-requirements.txt and remove +# this comment. RUN apt-get update && apt-get install -y --no-install-recommends \ g++ \ @@ -8,6 +11,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ ca-certificates \ python3 \ + python3-pip \ + python3-pkg-resources \ git \ cmake \ sudo \ @@ -27,6 +32,9 @@ RUN npm install eslint@8.6.0 -g COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh +COPY host-x86_64/mingw-check/reuse-requirements.txt /tmp/ +RUN pip3 install --no-deps --require-hashes -r /tmp/reuse-requirements.txt + COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/ COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/ @@ -40,6 +48,7 @@ ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \ python3 ../x.py doc --stage 0 library/test && \ /scripts/validate-toolstate.sh && \ /scripts/validate-error-codes.sh && \ + reuse lint && \ # Runs checks to ensure that there are no ES5 issues in our JS code. es-check es6 ../src/librustdoc/html/static/js/*.js && \ eslint -c ../src/librustdoc/html/static/.eslintrc.js ../src/librustdoc/html/static/js/*.js diff --git a/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.in b/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.in new file mode 100644 index 00000000000..4964f40aa39 --- /dev/null +++ b/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.in @@ -0,0 +1,22 @@ +# This is the template for reuse-requirements.txt. +# +# The pip-tools project is used to generate the file again. To install it, the +# recommended way is to: +# +# - Install pipx from https://github.com/pypa/pipx +# - Run `pipx install pip-tools` +# +# Once pip-tools is installed, run this command to regenerate the .txt file: +# +# pip-compile --allow-unsafe --generate-hashes reuse-requirements.in +# + +reuse + +# Some packages dropped support for Python 3.6, which is the version used in +# this builder (due to Ubuntu 18.04). This should be removed once we bump the +# Ubuntu version of the builder. +jinja2 < 3.1 +markupsafe < 2.1 +requests < 2.28 +setuptools < 59.7 diff --git a/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.txt b/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.txt new file mode 100644 index 00000000000..10a5f738790 --- /dev/null +++ b/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.txt @@ -0,0 +1,145 @@ +# +# This file is autogenerated by pip-compile with python 3.10 +# To update, run: +# +# pip-compile --allow-unsafe --generate-hashes reuse-requirements.in +# +binaryornot==0.4.4 \ + --hash=sha256:359501dfc9d40632edc9fac890e19542db1a287bbcfa58175b66658392018061 \ + --hash=sha256:b8b71173c917bddcd2c16070412e369c3ed7f0528926f70cac18a6c97fd563e4 + # via reuse +boolean-py==3.8 \ + --hash=sha256:cc24e20f985d60cd4a3a5a1c0956dd12611159d32a75081dabd0c9ab981acaa4 \ + --hash=sha256:d75da0fd0354425fa64f6bbc6cec6ae1485d0eec3447b73187ff8cbf9b572e26 + # via + # license-expression + # reuse +certifi==2022.6.15 \ + --hash=sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d \ + --hash=sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412 + # via requests +chardet==5.0.0 \ + --hash=sha256:0368df2bfd78b5fc20572bb4e9bb7fb53e2c094f60ae9993339e8671d0afb8aa \ + --hash=sha256:d3e64f022d254183001eccc5db4040520c0f23b1a3f33d6413e099eb7f126557 + # via + # binaryornot + # python-debian +charset-normalizer==2.0.12 \ + --hash=sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597 \ + --hash=sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df + # via requests +idna==3.3 \ + --hash=sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff \ + --hash=sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d + # via requests +jinja2==3.0.3 \ + --hash=sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8 \ + --hash=sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7 + # via + # -r reuse-requirements.in + # reuse +license-expression==21.6.14 \ + --hash=sha256:324246eed8e138b4139fefdc0e9dc4161d5075e3929e56983966d37298dca30e \ + --hash=sha256:9de87a427c9a449eee7913472fb9ed03b63036295547369fdbf95f76a8b924b2 + # via + # -r reuse-requirements.in + # reuse +markupsafe==2.0.1 \ + --hash=sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298 \ + --hash=sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64 \ + --hash=sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b \ + --hash=sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194 \ + --hash=sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567 \ + --hash=sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff \ + --hash=sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724 \ + --hash=sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74 \ + --hash=sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646 \ + --hash=sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35 \ + --hash=sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6 \ + --hash=sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a \ + --hash=sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6 \ + --hash=sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad \ + --hash=sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26 \ + --hash=sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38 \ + --hash=sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac \ + --hash=sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7 \ + --hash=sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6 \ + --hash=sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047 \ + --hash=sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75 \ + --hash=sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f \ + --hash=sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b \ + --hash=sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135 \ + --hash=sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8 \ + --hash=sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a \ + --hash=sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a \ + --hash=sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1 \ + --hash=sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9 \ + --hash=sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864 \ + --hash=sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914 \ + --hash=sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee \ + --hash=sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f \ + --hash=sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18 \ + --hash=sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8 \ + --hash=sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2 \ + --hash=sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d \ + --hash=sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b \ + --hash=sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b \ + --hash=sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86 \ + --hash=sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6 \ + --hash=sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f \ + --hash=sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb \ + --hash=sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833 \ + --hash=sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28 \ + --hash=sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e \ + --hash=sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415 \ + --hash=sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902 \ + --hash=sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f \ + --hash=sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d \ + --hash=sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9 \ + --hash=sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d \ + --hash=sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145 \ + --hash=sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066 \ + --hash=sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c \ + --hash=sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1 \ + --hash=sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a \ + --hash=sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207 \ + --hash=sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f \ + --hash=sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53 \ + --hash=sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd \ + --hash=sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134 \ + --hash=sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85 \ + --hash=sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9 \ + --hash=sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5 \ + --hash=sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94 \ + --hash=sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509 \ + --hash=sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51 \ + --hash=sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872 + # via + # -r reuse-requirements.in + # jinja2 +python-debian==0.1.44 \ + --hash=sha256:11bd6f01c46da57982bdd66dd595e2d240feb32a85de3fd37c452102fd0337ab \ + --hash=sha256:65592fe3b64f6c6c93d94e2d2599db5e0c22831d3bcff07cb7b96d3840b1333e + # via reuse +requests==2.26.0 \ + --hash=sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24 \ + --hash=sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7 + # via + # -r reuse-requirements.in + # reuse +reuse==1.0.0 \ + --hash=sha256:db3022be2d87f69c8f508b928023de3026f454ce17d01e22f770f7147ac1e8d4 \ + --hash=sha256:e2605e796311c424465d741ea2a1e1ad03bbb90b921d74750119c331ca5af46e + # via -r reuse-requirements.in +urllib3==1.26.10 \ + --hash=sha256:8298d6d56d39be0e3bc13c1c97d133f9b45d797169a0e11cdd0e0489d786f7ec \ + --hash=sha256:879ba4d1e89654d9769ce13121e0f94310ea32e8d2f8cf587b77c08bbcdb30d6 + # via requests + +# The following packages are considered to be unsafe in a requirements file: +setuptools==59.6.0 \ + --hash=sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373 \ + --hash=sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e + # via + # -r reuse-requirements.in + # reuse -- cgit 1.4.1-3-g733a5 From d4819632e2d0e135cff3e1987b77ca584e22a41a Mon Sep 17 00:00:00 2001 From: "Bruce A. MacNaughton" Date: Tue, 19 Jul 2022 17:35:19 -0700 Subject: working updates --- .../unicode-table-generator/src/cascading_map.rs | 90 ++++++++++++++++++++++ src/tools/unicode-table-generator/src/main.rs | 10 ++- .../unicode-table-generator/src/raw_emitter.rs | 10 +++ 3 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 src/tools/unicode-table-generator/src/cascading_map.rs diff --git a/src/tools/unicode-table-generator/src/cascading_map.rs b/src/tools/unicode-table-generator/src/cascading_map.rs new file mode 100644 index 00000000000..780d32e969c --- /dev/null +++ b/src/tools/unicode-table-generator/src/cascading_map.rs @@ -0,0 +1,90 @@ +use crate::fmt_list; +use crate::raw_emitter::RawEmitter; +use std::collections::HashMap; +use std::fmt::Write as _; +use std::ops::Range; + + +impl RawEmitter { + pub fn emit_cascading_map(&mut self, ranges: &[Range]) -> bool { + + let mut map: [u8; 256] = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + + let points = ranges.iter().flat_map( + |r| (r.start..r.end).into_iter().collect::>() + ).collect::>(); + + println!("there are {} points", points.len()); + + // how many distinct ranges need to be counted? + let mut codepoints_by_high_bytes = HashMap::>::new(); + for point in points { + // assert that there is no whitespace over the 0x3000 range. + assert!(point <= 0x3000, "the highest unicode whitespace value has changed"); + let high_bytes = point as usize >> 8; + let codepoints = codepoints_by_high_bytes.entry(high_bytes).or_insert_with(Vec::new); + codepoints.push(point); + } + + let mut bit_for_high_byte = 1u8; + let mut arms = Vec::::new(); + + let mut high_bytes: Vec = codepoints_by_high_bytes.keys().map(|k| k.clone()).collect(); + high_bytes.sort(); + for high_byte in high_bytes { + let codepoints = codepoints_by_high_bytes.get_mut(&high_byte).unwrap(); + if codepoints.len() == 1 { + let ch = codepoints.pop().unwrap(); + arms.push(format!("{} => c as u32 == {:#04x}", high_byte, ch)); + continue; + } + // more than 1 codepoint in this arm + for codepoint in codepoints { + map[(*codepoint & 0xff) as usize] |= bit_for_high_byte; + } + arms.push(format!( + "{} => WHITESPACE_MAP[c as usize & 0xff] & {} != 0", + high_byte, + bit_for_high_byte) + ); + bit_for_high_byte <<= 1; + } + + writeln!( + &mut self.file, + "static WHITESPACE_MAP: [u8; 256] = [{}];", + fmt_list(map.iter()) + ) + .unwrap(); + self.bytes_used += 256; + + + writeln!(&mut self.file, "pub fn lookup(c: char) -> bool {{").unwrap(); + writeln!(&mut self.file, " match c as u32 >> 8 {{").unwrap(); + for arm in arms { + writeln!(&mut self.file, " {},", arm).unwrap(); + } + writeln!(&mut self.file, " _ => false,").unwrap(); + writeln!(&mut self.file, " }}").unwrap(); + writeln!(&mut self.file, "}}").unwrap(); + + true + } +} diff --git a/src/tools/unicode-table-generator/src/main.rs b/src/tools/unicode-table-generator/src/main.rs index 4720ee7020f..b40afcf4bf2 100644 --- a/src/tools/unicode-table-generator/src/main.rs +++ b/src/tools/unicode-table-generator/src/main.rs @@ -78,9 +78,10 @@ use ucd_parse::Codepoints; mod case_mapping; mod raw_emitter; mod skiplist; +mod cascading_map; mod unicode_download; -use raw_emitter::{emit_codepoints, RawEmitter}; +use raw_emitter::{emit_codepoints, emit_whitespace, RawEmitter}; static PROPERTIES: &[&str] = &[ "Alphabetic", @@ -241,8 +242,13 @@ fn main() { let mut modules = Vec::new(); for (property, ranges) in ranges_by_property { let datapoints = ranges.iter().map(|r| r.end - r.start).sum::(); + let mut emitter = RawEmitter::new(); - emit_codepoints(&mut emitter, &ranges); + if property == &"White_Space" { + emit_whitespace(&mut emitter, &ranges); + } else { + emit_codepoints(&mut emitter, &ranges); + } modules.push((property.to_lowercase().to_string(), emitter.file)); println!( diff --git a/src/tools/unicode-table-generator/src/raw_emitter.rs b/src/tools/unicode-table-generator/src/raw_emitter.rs index ab8eaee9541..f5960c45920 100644 --- a/src/tools/unicode-table-generator/src/raw_emitter.rs +++ b/src/tools/unicode-table-generator/src/raw_emitter.rs @@ -170,6 +170,16 @@ pub fn emit_codepoints(emitter: &mut RawEmitter, ranges: &[Range]) { } } +pub fn emit_whitespace(emitter: &mut RawEmitter, ranges: &[Range]) { + emitter.blank_line(); + + let mut cascading = emitter.clone(); + cascading.emit_cascading_map(&ranges); + *emitter = cascading; + emitter.desc = String::from("cascading"); + +} + struct Canonicalized { canonical_words: Vec, canonicalized_words: Vec<(u8, u8)>, -- cgit 1.4.1-3-g733a5 From 89ace470dcc0d4e08c1fd530e938893f87dcd436 Mon Sep 17 00:00:00 2001 From: "Bruce A. MacNaughton" Date: Tue, 19 Jul 2022 18:03:18 -0700 Subject: formatted --- .../unicode-table-generator/src/cascading_map.rs | 51 ++++++++-------------- src/tools/unicode-table-generator/src/main.rs | 2 +- .../unicode-table-generator/src/raw_emitter.rs | 1 - 3 files changed, 20 insertions(+), 34 deletions(-) diff --git a/src/tools/unicode-table-generator/src/cascading_map.rs b/src/tools/unicode-table-generator/src/cascading_map.rs index 780d32e969c..d4efdef2e80 100644 --- a/src/tools/unicode-table-generator/src/cascading_map.rs +++ b/src/tools/unicode-table-generator/src/cascading_map.rs @@ -4,32 +4,24 @@ use std::collections::HashMap; use std::fmt::Write as _; use std::ops::Range; - impl RawEmitter { pub fn emit_cascading_map(&mut self, ranges: &[Range]) -> bool { - let mut map: [u8; 256] = [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; - let points = ranges.iter().flat_map( - |r| (r.start..r.end).into_iter().collect::>() - ).collect::>(); + let points = ranges + .iter() + .flat_map(|r| (r.start..r.end).into_iter().collect::>()) + .collect::>(); println!("there are {} points", points.len()); @@ -46,7 +38,8 @@ impl RawEmitter { let mut bit_for_high_byte = 1u8; let mut arms = Vec::::new(); - let mut high_bytes: Vec = codepoints_by_high_bytes.keys().map(|k| k.clone()).collect(); + let mut high_bytes: Vec = + codepoints_by_high_bytes.keys().map(|k| k.clone()).collect(); high_bytes.sort(); for high_byte in high_bytes { let codepoints = codepoints_by_high_bytes.get_mut(&high_byte).unwrap(); @@ -61,21 +54,15 @@ impl RawEmitter { } arms.push(format!( "{} => WHITESPACE_MAP[c as usize & 0xff] & {} != 0", - high_byte, - bit_for_high_byte) - ); + high_byte, bit_for_high_byte + )); bit_for_high_byte <<= 1; } - writeln!( - &mut self.file, - "static WHITESPACE_MAP: [u8; 256] = [{}];", - fmt_list(map.iter()) - ) - .unwrap(); + writeln!(&mut self.file, "static WHITESPACE_MAP: [u8; 256] = [{}];", fmt_list(map.iter())) + .unwrap(); self.bytes_used += 256; - writeln!(&mut self.file, "pub fn lookup(c: char) -> bool {{").unwrap(); writeln!(&mut self.file, " match c as u32 >> 8 {{").unwrap(); for arm in arms { diff --git a/src/tools/unicode-table-generator/src/main.rs b/src/tools/unicode-table-generator/src/main.rs index b40afcf4bf2..a3327a3c2ff 100644 --- a/src/tools/unicode-table-generator/src/main.rs +++ b/src/tools/unicode-table-generator/src/main.rs @@ -75,10 +75,10 @@ use std::collections::{BTreeMap, HashMap}; use std::ops::Range; use ucd_parse::Codepoints; +mod cascading_map; mod case_mapping; mod raw_emitter; mod skiplist; -mod cascading_map; mod unicode_download; use raw_emitter::{emit_codepoints, emit_whitespace, RawEmitter}; diff --git a/src/tools/unicode-table-generator/src/raw_emitter.rs b/src/tools/unicode-table-generator/src/raw_emitter.rs index f5960c45920..5aca86ba089 100644 --- a/src/tools/unicode-table-generator/src/raw_emitter.rs +++ b/src/tools/unicode-table-generator/src/raw_emitter.rs @@ -177,7 +177,6 @@ pub fn emit_whitespace(emitter: &mut RawEmitter, ranges: &[Range]) { cascading.emit_cascading_map(&ranges); *emitter = cascading; emitter.desc = String::from("cascading"); - } struct Canonicalized { -- cgit 1.4.1-3-g733a5 From e5d4de39128205eb322c1e38219c0969c9af625b Mon Sep 17 00:00:00 2001 From: "Bruce A. MacNaughton" Date: Tue, 19 Jul 2022 18:03:33 -0700 Subject: generated code --- library/core/src/unicode/unicode_data.rs | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index d2073f86c01..eb9334bdc6d 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -544,18 +544,25 @@ pub mod uppercase { #[rustfmt::skip] pub mod white_space { - static SHORT_OFFSET_RUNS: [u32; 4] = [ - 5760, 18882560, 23080960, 40972289, - ]; - static OFFSETS: [u8; 21] = [ - 9, 5, 18, 1, 100, 1, 26, 1, 0, 1, 0, 11, 29, 2, 5, 1, 47, 1, 0, 1, 0, + static WHITESPACE_MAP: [u8; 256] = [ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; pub fn lookup(c: char) -> bool { - super::skip_search( - c as u32, - &SHORT_OFFSET_RUNS, - &OFFSETS, - ) + match c as u32 >> 8 { + 0 => WHITESPACE_MAP[c as usize & 0xff] & 1 != 0, + 22 => c as u32 == 0x1680, + 32 => WHITESPACE_MAP[c as usize & 0xff] & 2 != 0, + 48 => c as u32 == 0x3000, + _ => false, + } } } -- cgit 1.4.1-3-g733a5 From 5d048eb69dc73aa6307f07ad6a21eee5e3e64c9f Mon Sep 17 00:00:00 2001 From: "Bruce A. MacNaughton" Date: Wed, 20 Jul 2022 16:13:54 -0700 Subject: add #inline --- library/core/src/unicode/unicode_data.rs | 1 + src/tools/unicode-table-generator/src/cascading_map.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index eb9334bdc6d..c1eff3a36e6 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -555,6 +555,7 @@ pub mod white_space { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; + #[inline] pub fn lookup(c: char) -> bool { match c as u32 >> 8 { 0 => WHITESPACE_MAP[c as usize & 0xff] & 1 != 0, diff --git a/src/tools/unicode-table-generator/src/cascading_map.rs b/src/tools/unicode-table-generator/src/cascading_map.rs index d4efdef2e80..02c7542309a 100644 --- a/src/tools/unicode-table-generator/src/cascading_map.rs +++ b/src/tools/unicode-table-generator/src/cascading_map.rs @@ -63,6 +63,7 @@ impl RawEmitter { .unwrap(); self.bytes_used += 256; + writeln!(&mut self.file, "#[inline]").unwrap(); writeln!(&mut self.file, "pub fn lookup(c: char) -> bool {{").unwrap(); writeln!(&mut self.file, " match c as u32 >> 8 {{").unwrap(); for arm in arms { -- cgit 1.4.1-3-g733a5 From 321419ec42dcff403a54cd1153fefdecf50161da Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Thu, 21 Jul 2022 13:15:29 -0400 Subject: Box::from(slice): Clarify that contents are copied A colleague mentioned that they interpreted the old text as saying that only the pointer and the length are copied. Add a clause so it is more clear that the pointed to contents are also copied. --- library/alloc/src/boxed.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index c1ceeb0deb8..d2dca6cab03 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1480,7 +1480,7 @@ impl From<&[T]> for Box<[T]> { /// Converts a `&[T]` into a `Box<[T]>` /// /// This conversion allocates on the heap - /// and performs a copy of `slice`. + /// and performs a copy of `slice` and its contents. /// /// # Examples /// ```rust -- cgit 1.4.1-3-g733a5 From 0fed1a5f57fc8ffba7dccfddbfffeb77282888b9 Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Fri, 1 Jul 2022 13:01:41 -0700 Subject: Enable raw-dylib for binaries --- src/archive.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/archive.rs b/src/archive.rs index 0812f930b5d..f3f3628fcee 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -204,12 +204,16 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { any_members } - fn inject_dll_import_lib( - &mut self, + fn sess(&self) -> &Session { + self.sess + } + + fn create_dll_import_lib( + _sess: &Session, _lib_name: &str, _dll_imports: &[rustc_session::cstore::DllImport], - _tmpdir: &rustc_data_structures::temp_dir::MaybeTempDir, - ) { - bug!("injecting dll imports is not supported"); + _tmpdir: &Path, + ) -> PathBuf { + bug!("creating dll imports is not supported"); } } -- cgit 1.4.1-3-g733a5 From 395d564f2592c8981b74b14305100c32ae7c53cb Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 14 Jun 2022 16:28:07 +0000 Subject: Use object instead of LLVM for reading bitcode from rlibs --- Cargo.lock | 1 + compiler/rustc_codegen_llvm/Cargo.toml | 1 + compiler/rustc_codegen_llvm/src/back/lto.rs | 21 ++++++++++++++++----- compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs | 11 ----------- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 1 - compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp | 13 ------------- 6 files changed, 18 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ed3e30342f2..02f0bec2487 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3692,6 +3692,7 @@ dependencies = [ "libc", "libloading", "measureme", + "object 0.29.0", "rustc-demangle", "rustc_ast", "rustc_attr", diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index f9a5463efcd..74115353aaf 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -13,6 +13,7 @@ cstr = "0.2" libc = "0.2" libloading = "0.7.1" measureme = "10.0.0" +object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "archive", "coff", "elf", "macho", "pe"] } tracing = "0.1" rustc_middle = { path = "../rustc_middle" } rustc-demangle = "0.1.21" diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 3731c6bcfe7..e4af6269abc 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -1,15 +1,16 @@ use crate::back::write::{ self, save_temp_bitcode, to_llvm_opt_settings, with_llvm_pmb, DiagnosticHandlers, }; -use crate::llvm::archive_ro::ArchiveRO; use crate::llvm::{self, build_string, False, True}; use crate::{llvm_util, LlvmCodegenBackend, ModuleLlvm}; +use object::read::archive::ArchiveFile; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared}; use rustc_codegen_ssa::back::symbol_export; use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, TargetMachineFactoryConfig}; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{looks_like_rust_object_file, ModuleCodegen, ModuleKind}; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::memmap::Mmap; use rustc_errors::{FatalError, Handler}; use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::bug; @@ -107,14 +108,24 @@ fn prepare_lto( .extend(exported_symbols[&cnum].iter().filter_map(symbol_filter)); } - let archive = ArchiveRO::open(path).expect("wanted an rlib"); + let archive_data = unsafe { + Mmap::map(std::fs::File::open(&path).expect("couldn't open rlib")) + .expect("couldn't map rlib") + }; + let archive = ArchiveFile::parse(&*archive_data).expect("wanted an rlib"); let obj_files = archive - .iter() - .filter_map(|child| child.ok().and_then(|c| c.name().map(|name| (name, c)))) + .members() + .filter_map(|child| { + child.ok().and_then(|c| { + std::str::from_utf8(c.name()).ok().map(|name| (name.trim(), c)) + }) + }) .filter(|&(name, _)| looks_like_rust_object_file(name)); for (name, child) in obj_files { info!("adding bitcode from {}", name); - match get_bitcode_slice_from_object_data(child.data()) { + match get_bitcode_slice_from_object_data( + child.data(&*archive_data).expect("corrupt rlib"), + ) { Ok(data) => { let module = SerializedModule::FromRlib(data.to_vec()); upstream_modules.push((module, CString::new(name).unwrap())); diff --git a/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs b/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs index 64db4f7462d..7d948970223 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs @@ -83,17 +83,6 @@ impl<'a> Child<'a> { } } } - - pub fn data(&self) -> &'a [u8] { - unsafe { - let mut data_len = 0; - let data_ptr = super::LLVMRustArchiveChildData(self.raw, &mut data_len); - if data_ptr.is_null() { - panic!("failed to read data from archive child"); - } - slice::from_raw_parts(data_ptr as *const u8, data_len as usize) - } - } } impl<'a> Drop for Child<'a> { diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index f64eb79b0a8..f465be6cf1a 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2374,7 +2374,6 @@ extern "C" { AIR: &ArchiveIterator<'a>, ) -> Option<&'a mut ArchiveChild<'a>>; pub fn LLVMRustArchiveChildName(ACR: &ArchiveChild<'_>, size: &mut size_t) -> *const c_char; - pub fn LLVMRustArchiveChildData(ACR: &ArchiveChild<'_>, size: &mut size_t) -> *const c_char; pub fn LLVMRustArchiveChildFree<'a>(ACR: &'a mut ArchiveChild<'a>); pub fn LLVMRustArchiveIteratorFree<'a>(AIR: &'a mut ArchiveIterator<'a>); pub fn LLVMRustDestroyArchive(AR: &'static mut Archive); diff --git a/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp index 97541e615da..448a1f62f69 100644 --- a/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp @@ -154,19 +154,6 @@ LLVMRustArchiveChildName(LLVMRustArchiveChildConstRef Child, size_t *Size) { return Name.data(); } -extern "C" const char *LLVMRustArchiveChildData(LLVMRustArchiveChildRef Child, - size_t *Size) { - StringRef Buf; - Expected BufOrErr = Child->getBuffer(); - if (!BufOrErr) { - LLVMRustSetLastError(toString(BufOrErr.takeError()).c_str()); - return nullptr; - } - Buf = BufOrErr.get(); - *Size = Buf.size(); - return Buf.data(); -} - extern "C" LLVMRustArchiveMemberRef LLVMRustArchiveMemberNew(char *Filename, char *Name, LLVMRustArchiveChildRef Child) { -- cgit 1.4.1-3-g733a5 From fab36d1713504824be4eefdd7614cf9e79ca7358 Mon Sep 17 00:00:00 2001 From: sigaloid <69441971+sigaloid@users.noreply.github.com> Date: Mon, 25 Jul 2022 21:58:30 -0400 Subject: Add comments about stdout locking --- library/std/src/macros.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs index 0cb21ef53b1..00473f50a63 100644 --- a/library/std/src/macros.rs +++ b/library/std/src/macros.rs @@ -27,12 +27,23 @@ macro_rules! panic { /// necessary to use [`io::stdout().flush()`][flush] to ensure the output is emitted /// immediately. /// +/// The `print!` macro will lock the standard output on each call. If you call +/// `print!` within a hot loop, this behavior may be the bottleneck of the loop. +/// To avoid this, lock stdout with [`io::stdout().lock()`][lock]: +/// ``` +/// use std::io::{stdout, Write}; +/// +/// let mut lock = stdout().lock(); +/// write!(lock, "hello world").unwrap(); +/// ``` +/// /// Use `print!` only for the primary output of your program. Use /// [`eprint!`] instead to print error and progress messages. /// /// [flush]: crate::io::Write::flush /// [`println!`]: crate::println /// [`eprint!`]: crate::eprint +/// [lock]: crate::io::Stdout /// /// # Panics /// @@ -75,11 +86,22 @@ macro_rules! print { /// This macro uses the same syntax as [`format!`], but writes to the standard output instead. /// See [`std::fmt`] for more information. /// +/// The `println!` macro will lock the standard output on each call. If you call +/// `println!` within a hot loop, this behavior may be the bottleneck of the loop. +/// To avoid this, lock stdout with [`io::stdout().lock()`][lock]: +/// ``` +/// use std::io::{stdout, Write}; +/// +/// let mut lock = stdout().lock(); +/// writeln!(lock, "hello world").unwrap(); +/// ``` +/// /// Use `println!` only for the primary output of your program. Use /// [`eprintln!`] instead to print error and progress messages. /// /// [`std::fmt`]: crate::fmt /// [`eprintln!`]: crate::eprintln +/// [lock]: crate::io::Stdout /// /// # Panics /// -- cgit 1.4.1-3-g733a5 From a6260ecd81e2eb928b7532649888e0b19540f82f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 26 Jul 2022 18:53:46 +0200 Subject: Merge commit 'd3a2366ee877075c59b38bd8ced55f224fc7ef51' into sync_cg_clif-2022-07-26 --- src/intrinsics/llvm.rs | 145 +++++++----- src/intrinsics/mod.rs | 622 +++++++++++++++++++++++++++++-------------------- src/intrinsics/simd.rs | 399 +++++++++++++++++++------------ 3 files changed, 705 insertions(+), 461 deletions(-) diff --git a/src/intrinsics/llvm.rs b/src/intrinsics/llvm.rs index 77ac46540a9..869670c8cfa 100644 --- a/src/intrinsics/llvm.rs +++ b/src/intrinsics/llvm.rs @@ -13,15 +13,11 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( ret: CPlace<'tcx>, target: Option, ) { - intrinsic_match! { - fx, intrinsic, args, - _ => { - fx.tcx.sess.warn(&format!("unsupported llvm intrinsic {}; replacing with trap", intrinsic)); - crate::trap::trap_unimplemented(fx, intrinsic); - }; - + match intrinsic { // Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8` - "llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd", (c a) { + "llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd" => { + intrinsic_args!(fx, args => (a); intrinsic); + let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx); let lane_ty = fx.clif_type(lane_ty).unwrap(); assert!(lane_count <= 32); @@ -29,7 +25,8 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( let mut res = fx.bcx.ins().iconst(types::I32, 0); for lane in (0..lane_count).rev() { - let a_lane = a.value_field(fx, mir::Field::new(lane.try_into().unwrap())).load_scalar(fx); + let a_lane = + a.value_field(fx, mir::Field::new(lane.try_into().unwrap())).load_scalar(fx); // cast float to int let a_lane = match lane_ty { @@ -49,26 +46,29 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( let res = CValue::by_val(res, fx.layout_of(fx.tcx.types.i32)); ret.write_cvalue(fx, res); - }; - "llvm.x86.sse2.cmp.ps" | "llvm.x86.sse2.cmp.pd", (c x, c y, o kind) { - let kind = crate::constant::mir_operand_get_const_val(fx, kind).expect("llvm.x86.sse2.cmp.* kind not const"); - let flt_cc = match kind.try_to_bits(Size::from_bytes(1)).unwrap_or_else(|| panic!("kind not scalar: {:?}", kind)) { + } + "llvm.x86.sse2.cmp.ps" | "llvm.x86.sse2.cmp.pd" => { + let (x, y, kind) = match args { + [x, y, kind] => (x, y, kind), + _ => bug!("wrong number of args for intrinsic {intrinsic}"), + }; + let x = codegen_operand(fx, x); + let y = codegen_operand(fx, y); + let kind = crate::constant::mir_operand_get_const_val(fx, kind) + .expect("llvm.x86.sse2.cmp.* kind not const"); + + let flt_cc = match kind + .try_to_bits(Size::from_bytes(1)) + .unwrap_or_else(|| panic!("kind not scalar: {:?}", kind)) + { 0 => FloatCC::Equal, 1 => FloatCC::LessThan, 2 => FloatCC::LessThanOrEqual, - 7 => { - unimplemented!("Compares corresponding elements in `a` and `b` to see if neither is `NaN`."); - } - 3 => { - unimplemented!("Compares corresponding elements in `a` and `b` to see if either is `NaN`."); - } + 7 => FloatCC::Ordered, + 3 => FloatCC::Unordered, 4 => FloatCC::NotEqual, - 5 => { - unimplemented!("not less than"); - } - 6 => { - unimplemented!("not less than or equal"); - } + 5 => FloatCC::UnorderedOrGreaterThanOrEqual, + 6 => FloatCC::UnorderedOrGreaterThan, kind => unreachable!("kind {:?}", kind), }; @@ -79,50 +79,67 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( }; bool_to_zero_or_max_uint(fx, res_lane_ty, res_lane) }); - }; - "llvm.x86.sse2.psrli.d", (c a, o imm8) { - let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8).expect("llvm.x86.sse2.psrli.d imm8 not const"); - simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| { - match imm8.try_to_bits(Size::from_bytes(4)).unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) { - imm8 if imm8 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm8 as u8)), - _ => fx.bcx.ins().iconst(types::I32, 0), - } + } + "llvm.x86.sse2.psrli.d" => { + let (a, imm8) = match args { + [a, imm8] => (a, imm8), + _ => bug!("wrong number of args for intrinsic {intrinsic}"), + }; + let a = codegen_operand(fx, a); + let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8) + .expect("llvm.x86.sse2.psrli.d imm8 not const"); + + simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8 + .try_to_bits(Size::from_bytes(4)) + .unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) + { + imm8 if imm8 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm8 as u8)), + _ => fx.bcx.ins().iconst(types::I32, 0), }); - }; - "llvm.x86.sse2.pslli.d", (c a, o imm8) { - let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8).expect("llvm.x86.sse2.psrli.d imm8 not const"); - simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| { - match imm8.try_to_bits(Size::from_bytes(4)).unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) { - imm8 if imm8 < 32 => fx.bcx.ins().ishl_imm(lane, i64::from(imm8 as u8)), - _ => fx.bcx.ins().iconst(types::I32, 0), - } + } + "llvm.x86.sse2.pslli.d" => { + let (a, imm8) = match args { + [a, imm8] => (a, imm8), + _ => bug!("wrong number of args for intrinsic {intrinsic}"), + }; + let a = codegen_operand(fx, a); + let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8) + .expect("llvm.x86.sse2.psrli.d imm8 not const"); + + simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8 + .try_to_bits(Size::from_bytes(4)) + .unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) + { + imm8 if imm8 < 32 => fx.bcx.ins().ishl_imm(lane, i64::from(imm8 as u8)), + _ => fx.bcx.ins().iconst(types::I32, 0), }); - }; - "llvm.x86.sse2.storeu.dq", (v mem_addr, c a) { + } + "llvm.x86.sse2.storeu.dq" => { + intrinsic_args!(fx, args => (mem_addr, a); intrinsic); + let mem_addr = mem_addr.load_scalar(fx); + // FIXME correctly handle the unalignment let dest = CPlace::for_ptr(Pointer::new(mem_addr), a.layout()); dest.write_cvalue(fx, a); - }; - "llvm.x86.addcarry.64", (v c_in, c a, c b) { - llvm_add_sub( - fx, - BinOp::Add, - ret, - c_in, - a, - b - ); - }; - "llvm.x86.subborrow.64", (v b_in, c a, c b) { - llvm_add_sub( - fx, - BinOp::Sub, - ret, - b_in, - a, - b - ); - }; + } + "llvm.x86.addcarry.64" => { + intrinsic_args!(fx, args => (c_in, a, b); intrinsic); + let c_in = c_in.load_scalar(fx); + + llvm_add_sub(fx, BinOp::Add, ret, c_in, a, b); + } + "llvm.x86.subborrow.64" => { + intrinsic_args!(fx, args => (b_in, a, b); intrinsic); + let b_in = b_in.load_scalar(fx); + + llvm_add_sub(fx, BinOp::Sub, ret, b_in, a, b); + } + _ => { + fx.tcx + .sess + .warn(&format!("unsupported llvm intrinsic {}; replacing with trap", intrinsic)); + crate::trap::trap_unimplemented(fx, intrinsic); + } } let dest = target.expect("all llvm intrinsics used by stdlib should return"); diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 8d8db1da581..b2a83e1d4eb 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -1,50 +1,14 @@ //! Codegen of intrinsics. This includes `extern "rust-intrinsic"`, `extern "platform-intrinsic"` //! and LLVM intrinsics that have symbol names starting with `llvm.`. -macro_rules! intrinsic_pat { - (_) => { - _ - }; - ($name:ident) => { - sym::$name - }; - (kw.$name:ident) => { - kw::$name - }; - ($name:literal) => { - $name - }; -} - -macro_rules! intrinsic_arg { - (o $fx:expr, $arg:ident) => {}; - (c $fx:expr, $arg:ident) => { - let $arg = codegen_operand($fx, $arg); - }; - (v $fx:expr, $arg:ident) => { - let $arg = codegen_operand($fx, $arg).load_scalar($fx); - }; -} - -macro_rules! intrinsic_match { - ($fx:expr, $intrinsic:expr, $args:expr, - _ => $unknown:block; - $( - $($($name:tt).*)|+ $(if $cond:expr)?, ($($a:ident $arg:ident),*) $content:block; - )*) => { - match $intrinsic { - $( - $(intrinsic_pat!($($name).*))|* $(if $cond)? => { - if let [$($arg),*] = $args { - $(intrinsic_arg!($a $fx, $arg);)* - $content - } else { - bug!("wrong number of args for intrinsic {:?}", $intrinsic); - } - } - )* - _ => $unknown, - } +macro_rules! intrinsic_args { + ($fx:expr, $args:expr => ($($arg:tt),*); $intrinsic:expr) => { + #[allow(unused_parens)] + let ($($arg),*) = if let [$($arg),*] = $args { + ($(codegen_operand($fx, $arg)),*) + } else { + $crate::intrinsics::bug_on_incorrect_arg_count($intrinsic); + }; } } @@ -62,6 +26,10 @@ use rustc_span::symbol::{kw, sym, Symbol}; use crate::prelude::*; use cranelift_codegen::ir::AtomicRmwOp; +fn bug_on_incorrect_arg_count(intrinsic: impl std::fmt::Display) -> ! { + bug!("wrong number of args for intrinsic {}", intrinsic); +} + fn report_atomic_type_validation_error<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: Symbol, @@ -351,28 +319,31 @@ fn codegen_regular_intrinsic_call<'tcx>( ) { let usize_layout = fx.layout_of(fx.tcx.types.usize); - intrinsic_match! { - fx, intrinsic, args, - _ => { - fx.tcx.sess.span_fatal(source_info.span, &format!("unsupported intrinsic {}", intrinsic)); - }; + match intrinsic { + sym::assume => { + intrinsic_args!(fx, args => (_a); intrinsic); + } + sym::likely | sym::unlikely => { + intrinsic_args!(fx, args => (a); intrinsic); - assume, (c _a) {}; - likely | unlikely, (c a) { ret.write_cvalue(fx, a); - }; - breakpoint, () { + } + sym::breakpoint => { + intrinsic_args!(fx, args => (); intrinsic); + fx.bcx.ins().debugtrap(); - }; - copy | copy_nonoverlapping, (v src, v dst, v count) { + } + sym::copy | sym::copy_nonoverlapping => { + intrinsic_args!(fx, args => (src, dst, count); intrinsic); + let src = src.load_scalar(fx); + let dst = dst.load_scalar(fx); + let count = count.load_scalar(fx); + let elem_ty = substs.type_at(0); let elem_size: u64 = fx.layout_of(elem_ty).size.bytes(); assert_eq!(args.len(), 3); - let byte_amount = if elem_size != 1 { - fx.bcx.ins().imul_imm(count, elem_size as i64) - } else { - count - }; + let byte_amount = + if elem_size != 1 { fx.bcx.ins().imul_imm(count, elem_size as i64) } else { count }; if intrinsic == sym::copy_nonoverlapping { // FIXME emit_small_memcpy @@ -381,17 +352,19 @@ fn codegen_regular_intrinsic_call<'tcx>( // FIXME emit_small_memmove fx.bcx.call_memmove(fx.target_config, dst, src, byte_amount); } - }; - // NOTE: the volatile variants have src and dst swapped - volatile_copy_memory | volatile_copy_nonoverlapping_memory, (v dst, v src, v count) { + } + sym::volatile_copy_memory | sym::volatile_copy_nonoverlapping_memory => { + // NOTE: the volatile variants have src and dst swapped + intrinsic_args!(fx, args => (dst, src, count); intrinsic); + let dst = dst.load_scalar(fx); + let src = src.load_scalar(fx); + let count = count.load_scalar(fx); + let elem_ty = substs.type_at(0); let elem_size: u64 = fx.layout_of(elem_ty).size.bytes(); assert_eq!(args.len(), 3); - let byte_amount = if elem_size != 1 { - fx.bcx.ins().imul_imm(count, elem_size as i64) - } else { - count - }; + let byte_amount = + if elem_size != 1 { fx.bcx.ins().imul_imm(count, elem_size as i64) } else { count }; // FIXME make the copy actually volatile when using emit_small_mem{cpy,move} if intrinsic == sym::volatile_copy_nonoverlapping_memory { @@ -401,8 +374,10 @@ fn codegen_regular_intrinsic_call<'tcx>( // FIXME emit_small_memmove fx.bcx.call_memmove(fx.target_config, dst, src, byte_amount); } - }; - size_of_val, (c ptr) { + } + sym::size_of_val => { + intrinsic_args!(fx, args => (ptr); intrinsic); + let layout = fx.layout_of(substs.type_at(0)); // Note: Can't use is_unsized here as truly unsized types need to take the fixed size // branch @@ -411,14 +386,13 @@ fn codegen_regular_intrinsic_call<'tcx>( let (size, _align) = crate::unsize::size_and_align_of_dst(fx, layout, info); size } else { - fx - .bcx - .ins() - .iconst(fx.pointer_type, layout.size.bytes() as i64) + fx.bcx.ins().iconst(fx.pointer_type, layout.size.bytes() as i64) }; ret.write_cvalue(fx, CValue::by_val(size, usize_layout)); - }; - min_align_of_val, (c ptr) { + } + sym::min_align_of_val => { + intrinsic_args!(fx, args => (ptr); intrinsic); + let layout = fx.layout_of(substs.type_at(0)); // Note: Can't use is_unsized here as truly unsized types need to take the fixed size // branch @@ -427,26 +401,37 @@ fn codegen_regular_intrinsic_call<'tcx>( let (_size, align) = crate::unsize::size_and_align_of_dst(fx, layout, info); align } else { - fx - .bcx - .ins() - .iconst(fx.pointer_type, layout.align.abi.bytes() as i64) + fx.bcx.ins().iconst(fx.pointer_type, layout.align.abi.bytes() as i64) }; ret.write_cvalue(fx, CValue::by_val(align, usize_layout)); - }; + } + + sym::vtable_size => { + intrinsic_args!(fx, args => (vtable); intrinsic); + let vtable = vtable.load_scalar(fx); - vtable_size, (v vtable) { let size = crate::vtable::size_of_obj(fx, vtable); ret.write_cvalue(fx, CValue::by_val(size, usize_layout)); - }; + } + + sym::vtable_align => { + intrinsic_args!(fx, args => (vtable); intrinsic); + let vtable = vtable.load_scalar(fx); - vtable_align, (v vtable) { let align = crate::vtable::min_align_of_obj(fx, vtable); ret.write_cvalue(fx, CValue::by_val(align, usize_layout)); - }; + } + + sym::unchecked_add + | sym::unchecked_sub + | sym::unchecked_mul + | sym::unchecked_div + | sym::exact_div + | sym::unchecked_rem + | sym::unchecked_shl + | sym::unchecked_shr => { + intrinsic_args!(fx, args => (x, y); intrinsic); - unchecked_add | unchecked_sub | unchecked_mul | unchecked_div | exact_div | unchecked_rem - | unchecked_shl | unchecked_shr, (c x, c y) { // FIXME trap on overflow let bin_op = match intrinsic { sym::unchecked_add => BinOp::Add, @@ -460,8 +445,10 @@ fn codegen_regular_intrinsic_call<'tcx>( }; let res = crate::num::codegen_int_binop(fx, bin_op, x, y); ret.write_cvalue(fx, res); - }; - add_with_overflow | sub_with_overflow | mul_with_overflow, (c x, c y) { + } + sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => { + intrinsic_args!(fx, args => (x, y); intrinsic); + assert_eq!(x.layout().ty, y.layout().ty); let bin_op = match intrinsic { sym::add_with_overflow => BinOp::Add, @@ -470,15 +457,12 @@ fn codegen_regular_intrinsic_call<'tcx>( _ => unreachable!(), }; - let res = crate::num::codegen_checked_int_binop( - fx, - bin_op, - x, - y, - ); + let res = crate::num::codegen_checked_int_binop(fx, bin_op, x, y); ret.write_cvalue(fx, res); - }; - saturating_add | saturating_sub, (c lhs, c rhs) { + } + sym::saturating_add | sym::saturating_sub => { + intrinsic_args!(fx, args => (lhs, rhs); intrinsic); + assert_eq!(lhs.layout().ty, rhs.layout().ty); let bin_op = match intrinsic { sym::saturating_add => BinOp::Add, @@ -488,12 +472,7 @@ fn codegen_regular_intrinsic_call<'tcx>( let signed = type_sign(lhs.layout().ty); - let checked_res = crate::num::codegen_checked_int_binop( - fx, - bin_op, - lhs, - rhs, - ); + let checked_res = crate::num::codegen_checked_int_binop(fx, bin_op, lhs, rhs); let (val, has_overflow) = checked_res.load_scalar_pair(fx); let clif_ty = fx.clif_type(lhs.layout().ty).unwrap(); @@ -505,13 +484,15 @@ fn codegen_regular_intrinsic_call<'tcx>( (sym::saturating_sub, false) => fx.bcx.ins().select(has_overflow, min, val), (sym::saturating_add, true) => { let rhs = rhs.load_scalar(fx); - let rhs_ge_zero = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0); + let rhs_ge_zero = + fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0); let sat_val = fx.bcx.ins().select(rhs_ge_zero, max, min); fx.bcx.ins().select(has_overflow, sat_val, val) } (sym::saturating_sub, true) => { let rhs = rhs.load_scalar(fx); - let rhs_ge_zero = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0); + let rhs_ge_zero = + fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0); let sat_val = fx.bcx.ins().select(rhs_ge_zero, min, max); fx.bcx.ins().select(has_overflow, sat_val, val) } @@ -521,23 +502,32 @@ fn codegen_regular_intrinsic_call<'tcx>( let res = CValue::by_val(val, lhs.layout()); ret.write_cvalue(fx, res); - }; - rotate_left, (c x, v y) { + } + sym::rotate_left => { + intrinsic_args!(fx, args => (x, y); intrinsic); + let y = y.load_scalar(fx); + let layout = x.layout(); let x = x.load_scalar(fx); let res = fx.bcx.ins().rotl(x, y); ret.write_cvalue(fx, CValue::by_val(res, layout)); - }; - rotate_right, (c x, v y) { + } + sym::rotate_right => { + intrinsic_args!(fx, args => (x, y); intrinsic); + let y = y.load_scalar(fx); + let layout = x.layout(); let x = x.load_scalar(fx); let res = fx.bcx.ins().rotr(x, y); ret.write_cvalue(fx, CValue::by_val(res, layout)); - }; + } // The only difference between offset and arith_offset is regarding UB. Because Cranelift // doesn't have UB both are codegen'ed the same way - offset | arith_offset, (c base, v offset) { + sym::offset | sym::arith_offset => { + intrinsic_args!(fx, args => (base, offset); intrinsic); + let offset = offset.load_scalar(fx); + let pointee_ty = base.layout().ty.builtin_deref(true).unwrap().ty; let pointee_size = fx.layout_of(pointee_ty).size.bytes(); let ptr_diff = if pointee_size != 1 { @@ -548,12 +538,18 @@ fn codegen_regular_intrinsic_call<'tcx>( let base_val = base.load_scalar(fx); let res = fx.bcx.ins().iadd(base_val, ptr_diff); ret.write_cvalue(fx, CValue::by_val(res, base.layout())); - }; + } + + sym::transmute => { + intrinsic_args!(fx, args => (from); intrinsic); - transmute, (c from) { ret.write_cvalue_transmute(fx, from); - }; - write_bytes | volatile_set_memory, (c dst, v val, v count) { + } + sym::write_bytes | sym::volatile_set_memory => { + intrinsic_args!(fx, args => (dst, val, count); intrinsic); + let val = val.load_scalar(fx); + let count = count.load_scalar(fx); + let pointee_ty = dst.layout().ty.builtin_deref(true).unwrap().ty; let pointee_size = fx.layout_of(pointee_ty).size.bytes(); let count = if pointee_size != 1 { @@ -565,34 +561,42 @@ fn codegen_regular_intrinsic_call<'tcx>( // FIXME make the memset actually volatile when switching to emit_small_memset // FIXME use emit_small_memset fx.bcx.call_memset(fx.target_config, dst_ptr, val, count); - }; - ctlz | ctlz_nonzero, (c arg) { + } + sym::ctlz | sym::ctlz_nonzero => { + intrinsic_args!(fx, args => (arg); intrinsic); let val = arg.load_scalar(fx); + // FIXME trap on `ctlz_nonzero` with zero arg. let res = fx.bcx.ins().clz(val); let res = CValue::by_val(res, arg.layout()); ret.write_cvalue(fx, res); - }; - cttz | cttz_nonzero, (c arg) { + } + sym::cttz | sym::cttz_nonzero => { + intrinsic_args!(fx, args => (arg); intrinsic); let val = arg.load_scalar(fx); + // FIXME trap on `cttz_nonzero` with zero arg. let res = fx.bcx.ins().ctz(val); let res = CValue::by_val(res, arg.layout()); ret.write_cvalue(fx, res); - }; - ctpop, (c arg) { + } + sym::ctpop => { + intrinsic_args!(fx, args => (arg); intrinsic); let val = arg.load_scalar(fx); + let res = fx.bcx.ins().popcnt(val); let res = CValue::by_val(res, arg.layout()); ret.write_cvalue(fx, res); - }; - bitreverse, (c arg) { + } + sym::bitreverse => { + intrinsic_args!(fx, args => (arg); intrinsic); let val = arg.load_scalar(fx); + let res = fx.bcx.ins().bitrev(val); let res = CValue::by_val(res, arg.layout()); ret.write_cvalue(fx, res); - }; - bswap, (c arg) { + } + sym::bswap => { // FIXME(CraneStation/cranelift#794) add bswap instruction to cranelift fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value { match bcx.func.dfg.value_type(v) { @@ -668,11 +672,15 @@ fn codegen_regular_intrinsic_call<'tcx>( ty => unreachable!("bswap {}", ty), } } + intrinsic_args!(fx, args => (arg); intrinsic); let val = arg.load_scalar(fx); + let res = CValue::by_val(swap(&mut fx.bcx, val), arg.layout()); ret.write_cvalue(fx, res); - }; - assert_inhabited | assert_zero_valid | assert_uninit_valid, () { + } + sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => { + intrinsic_args!(fx, args => (); intrinsic); + let layout = fx.layout_of(substs.type_at(0)); if layout.abi.is_uninhabited() { with_no_trimmed_paths!({ @@ -689,7 +697,10 @@ fn codegen_regular_intrinsic_call<'tcx>( with_no_trimmed_paths!({ crate::base::codegen_panic( fx, - &format!("attempted to zero-initialize type `{}`, which is invalid", layout.ty), + &format!( + "attempted to zero-initialize type `{}`, which is invalid", + layout.ty + ), source_info, ); }); @@ -700,41 +711,53 @@ fn codegen_regular_intrinsic_call<'tcx>( with_no_trimmed_paths!({ crate::base::codegen_panic( fx, - &format!("attempted to leave type `{}` uninitialized, which is invalid", layout.ty), + &format!( + "attempted to leave type `{}` uninitialized, which is invalid", + layout.ty + ), source_info, ) }); return; } - }; + } + + sym::volatile_load | sym::unaligned_volatile_load => { + intrinsic_args!(fx, args => (ptr); intrinsic); - volatile_load | unaligned_volatile_load, (c ptr) { // Cranelift treats loads as volatile by default // FIXME correctly handle unaligned_volatile_load - let inner_layout = - fx.layout_of(ptr.layout().ty.builtin_deref(true).unwrap().ty); + let inner_layout = fx.layout_of(ptr.layout().ty.builtin_deref(true).unwrap().ty); let val = CValue::by_ref(Pointer::new(ptr.load_scalar(fx)), inner_layout); ret.write_cvalue(fx, val); - }; - volatile_store | unaligned_volatile_store, (v ptr, c val) { + } + sym::volatile_store | sym::unaligned_volatile_store => { + intrinsic_args!(fx, args => (ptr, val); intrinsic); + let ptr = ptr.load_scalar(fx); + // Cranelift treats stores as volatile by default // FIXME correctly handle unaligned_volatile_store let dest = CPlace::for_ptr(Pointer::new(ptr), val.layout()); dest.write_cvalue(fx, val); - }; + } + + sym::pref_align_of + | sym::needs_drop + | sym::type_id + | sym::type_name + | sym::variant_count => { + intrinsic_args!(fx, args => (); intrinsic); - pref_align_of | needs_drop | type_id | type_name | variant_count, () { let const_val = fx.tcx.const_eval_instance(ParamEnv::reveal_all(), instance, None).unwrap(); - let val = crate::constant::codegen_const_value( - fx, - const_val, - ret.layout().ty, - ); + let val = crate::constant::codegen_const_value(fx, const_val, ret.layout().ty); ret.write_cvalue(fx, val); - }; + } - ptr_offset_from | ptr_offset_from_unsigned, (v ptr, v base) { + sym::ptr_offset_from | sym::ptr_offset_from_unsigned => { + intrinsic_args!(fx, args => (ptr, base); intrinsic); + let ptr = ptr.load_scalar(fx); + let base = base.load_scalar(fx); let ty = substs.type_at(0); let pointee_size: u64 = fx.layout_of(ty).size.bytes(); @@ -750,31 +773,44 @@ fn codegen_regular_intrinsic_call<'tcx>( CValue::by_val(fx.bcx.ins().sdiv_imm(diff_bytes, pointee_size as i64), isize_layout) }; ret.write_cvalue(fx, val); - }; + } + + sym::ptr_guaranteed_eq => { + intrinsic_args!(fx, args => (a, b); intrinsic); - ptr_guaranteed_eq, (c a, c b) { let val = crate::num::codegen_ptr_binop(fx, BinOp::Eq, a, b); ret.write_cvalue(fx, val); - }; + } + + sym::ptr_guaranteed_ne => { + intrinsic_args!(fx, args => (a, b); intrinsic); - ptr_guaranteed_ne, (c a, c b) { let val = crate::num::codegen_ptr_binop(fx, BinOp::Ne, a, b); ret.write_cvalue(fx, val); - }; + } + + sym::caller_location => { + intrinsic_args!(fx, args => (); intrinsic); - caller_location, () { let caller_location = fx.get_caller_location(source_info); ret.write_cvalue(fx, caller_location); - }; + } + + _ if intrinsic.as_str().starts_with("atomic_fence") => { + intrinsic_args!(fx, args => (); intrinsic); - _ if intrinsic.as_str().starts_with("atomic_fence"), () { fx.bcx.ins().fence(); - }; - _ if intrinsic.as_str().starts_with("atomic_singlethreadfence"), () { + } + _ if intrinsic.as_str().starts_with("atomic_singlethreadfence") => { + intrinsic_args!(fx, args => (); intrinsic); + // FIXME use a compiler fence once Cranelift supports it fx.bcx.ins().fence(); - }; - _ if intrinsic.as_str().starts_with("atomic_load"), (v ptr) { + } + _ if intrinsic.as_str().starts_with("atomic_load") => { + intrinsic_args!(fx, args => (ptr); intrinsic); + let ptr = ptr.load_scalar(fx); + let ty = substs.type_at(0); match ty.kind() { ty::Uint(UintTy::U128) | ty::Int(IntTy::I128) => { @@ -786,7 +822,9 @@ fn codegen_regular_intrinsic_call<'tcx>( fx.bcx.ins().jump(ret_block, &[]); return; } else { - fx.tcx.sess.span_fatal(source_info.span, "128bit atomics not yet supported"); + fx.tcx + .sess + .span_fatal(source_info.span, "128bit atomics not yet supported"); } } ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -801,8 +839,11 @@ fn codegen_regular_intrinsic_call<'tcx>( let val = CValue::by_val(val, fx.layout_of(ty)); ret.write_cvalue(fx, val); - }; - _ if intrinsic.as_str().starts_with("atomic_store"), (v ptr, c val) { + } + _ if intrinsic.as_str().starts_with("atomic_store") => { + intrinsic_args!(fx, args => (ptr, val); intrinsic); + let ptr = ptr.load_scalar(fx); + let ty = substs.type_at(0); match ty.kind() { ty::Uint(UintTy::U128) | ty::Int(IntTy::I128) => { @@ -814,7 +855,9 @@ fn codegen_regular_intrinsic_call<'tcx>( fx.bcx.ins().jump(ret_block, &[]); return; } else { - fx.tcx.sess.span_fatal(source_info.span, "128bit atomics not yet supported"); + fx.tcx + .sess + .span_fatal(source_info.span, "128bit atomics not yet supported"); } } ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -827,8 +870,11 @@ fn codegen_regular_intrinsic_call<'tcx>( let val = val.load_scalar(fx); fx.bcx.ins().atomic_store(MemFlags::trusted(), val, ptr); - }; - _ if intrinsic.as_str().starts_with("atomic_xchg"), (v ptr, c new) { + } + _ if intrinsic.as_str().starts_with("atomic_xchg") => { + intrinsic_args!(fx, args => (ptr, new); intrinsic); + let ptr = ptr.load_scalar(fx); + let layout = new.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -845,8 +891,12 @@ fn codegen_regular_intrinsic_call<'tcx>( let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); - }; - _ if intrinsic.as_str().starts_with("atomic_cxchg"), (v ptr, c test_old, c new) { // both atomic_cxchg_* and atomic_cxchgweak_* + } + _ if intrinsic.as_str().starts_with("atomic_cxchg") => { + // both atomic_cxchg_* and atomic_cxchgweak_* + intrinsic_args!(fx, args => (ptr, test_old, new); intrinsic); + let ptr = ptr.load_scalar(fx); + let layout = new.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -862,11 +912,15 @@ fn codegen_regular_intrinsic_call<'tcx>( let old = fx.bcx.ins().atomic_cas(MemFlags::trusted(), ptr, test_old, new); let is_eq = fx.bcx.ins().icmp(IntCC::Equal, old, test_old); - let ret_val = CValue::by_val_pair(old, fx.bcx.ins().bint(types::I8, is_eq), ret.layout()); + let ret_val = + CValue::by_val_pair(old, fx.bcx.ins().bint(types::I8, is_eq), ret.layout()); ret.write_cvalue(fx, ret_val) - }; + } + + _ if intrinsic.as_str().starts_with("atomic_xadd") => { + intrinsic_args!(fx, args => (ptr, amount); intrinsic); + let ptr = ptr.load_scalar(fx); - _ if intrinsic.as_str().starts_with("atomic_xadd"), (v ptr, c amount) { let layout = amount.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -879,12 +933,16 @@ fn codegen_regular_intrinsic_call<'tcx>( let amount = amount.load_scalar(fx); - let old = fx.bcx.ins().atomic_rmw(ty, MemFlags::trusted(), AtomicRmwOp::Add, ptr, amount); + let old = + fx.bcx.ins().atomic_rmw(ty, MemFlags::trusted(), AtomicRmwOp::Add, ptr, amount); let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); - }; - _ if intrinsic.as_str().starts_with("atomic_xsub"), (v ptr, c amount) { + } + _ if intrinsic.as_str().starts_with("atomic_xsub") => { + intrinsic_args!(fx, args => (ptr, amount); intrinsic); + let ptr = ptr.load_scalar(fx); + let layout = amount.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -897,12 +955,16 @@ fn codegen_regular_intrinsic_call<'tcx>( let amount = amount.load_scalar(fx); - let old = fx.bcx.ins().atomic_rmw(ty, MemFlags::trusted(), AtomicRmwOp::Sub, ptr, amount); + let old = + fx.bcx.ins().atomic_rmw(ty, MemFlags::trusted(), AtomicRmwOp::Sub, ptr, amount); let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); - }; - _ if intrinsic.as_str().starts_with("atomic_and"), (v ptr, c src) { + } + _ if intrinsic.as_str().starts_with("atomic_and") => { + intrinsic_args!(fx, args => (ptr, src); intrinsic); + let ptr = ptr.load_scalar(fx); + let layout = src.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -919,8 +981,11 @@ fn codegen_regular_intrinsic_call<'tcx>( let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); - }; - _ if intrinsic.as_str().starts_with("atomic_or"), (v ptr, c src) { + } + _ if intrinsic.as_str().starts_with("atomic_or") => { + intrinsic_args!(fx, args => (ptr, src); intrinsic); + let ptr = ptr.load_scalar(fx); + let layout = src.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -937,8 +1002,11 @@ fn codegen_regular_intrinsic_call<'tcx>( let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); - }; - _ if intrinsic.as_str().starts_with("atomic_xor"), (v ptr, c src) { + } + _ if intrinsic.as_str().starts_with("atomic_xor") => { + intrinsic_args!(fx, args => (ptr, src); intrinsic); + let ptr = ptr.load_scalar(fx); + let layout = src.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -955,8 +1023,11 @@ fn codegen_regular_intrinsic_call<'tcx>( let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); - }; - _ if intrinsic.as_str().starts_with("atomic_nand"), (v ptr, c src) { + } + _ if intrinsic.as_str().starts_with("atomic_nand") => { + intrinsic_args!(fx, args => (ptr, src); intrinsic); + let ptr = ptr.load_scalar(fx); + let layout = src.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -973,8 +1044,11 @@ fn codegen_regular_intrinsic_call<'tcx>( let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); - }; - _ if intrinsic.as_str().starts_with("atomic_max"), (v ptr, c src) { + } + _ if intrinsic.as_str().starts_with("atomic_max") => { + intrinsic_args!(fx, args => (ptr, src); intrinsic); + let ptr = ptr.load_scalar(fx); + let layout = src.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -991,8 +1065,11 @@ fn codegen_regular_intrinsic_call<'tcx>( let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); - }; - _ if intrinsic.as_str().starts_with("atomic_umax"), (v ptr, c src) { + } + _ if intrinsic.as_str().starts_with("atomic_umax") => { + intrinsic_args!(fx, args => (ptr, src); intrinsic); + let ptr = ptr.load_scalar(fx); + let layout = src.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -1009,8 +1086,11 @@ fn codegen_regular_intrinsic_call<'tcx>( let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); - }; - _ if intrinsic.as_str().starts_with("atomic_min"), (v ptr, c src) { + } + _ if intrinsic.as_str().starts_with("atomic_min") => { + intrinsic_args!(fx, args => (ptr, src); intrinsic); + let ptr = ptr.load_scalar(fx); + let layout = src.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -1027,8 +1107,11 @@ fn codegen_regular_intrinsic_call<'tcx>( let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); - }; - _ if intrinsic.as_str().starts_with("atomic_umin"), (v ptr, c src) { + } + _ if intrinsic.as_str().starts_with("atomic_umin") => { + intrinsic_args!(fx, args => (ptr, src); intrinsic); + let ptr = ptr.load_scalar(fx); + let layout = src.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -1045,30 +1128,51 @@ fn codegen_regular_intrinsic_call<'tcx>( let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); - }; + } + + sym::minnumf32 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); - minnumf32, (v a, v b) { let val = crate::num::codegen_float_min(fx, a, b); let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32)); ret.write_cvalue(fx, val); - }; - minnumf64, (v a, v b) { + } + sym::minnumf64 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + let val = crate::num::codegen_float_min(fx, a, b); let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64)); ret.write_cvalue(fx, val); - }; - maxnumf32, (v a, v b) { + } + sym::maxnumf32 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + let val = crate::num::codegen_float_max(fx, a, b); let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32)); ret.write_cvalue(fx, val); - }; - maxnumf64, (v a, v b) { + } + sym::maxnumf64 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + let val = crate::num::codegen_float_max(fx, a, b); let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64)); ret.write_cvalue(fx, val); - }; + } + + kw::Try => { + intrinsic_args!(fx, args => (f, data, catch_fn); intrinsic); + let f = f.load_scalar(fx); + let data = data.load_scalar(fx); + let _catch_fn = catch_fn.load_scalar(fx); - kw.Try, (v f, v data, v _catch_fn) { // FIXME once unwinding is supported, change this to actually catch panics let f_sig = fx.bcx.func.import_signature(Signature { call_conv: fx.target_config.default_call_conv, @@ -1081,20 +1185,30 @@ fn codegen_regular_intrinsic_call<'tcx>( let layout = ret.layout(); let ret_val = CValue::const_val(fx, layout, ty::ScalarInt::null(layout.size)); ret.write_cvalue(fx, ret_val); - }; + } - fadd_fast | fsub_fast | fmul_fast | fdiv_fast | frem_fast, (c x, c y) { - let res = crate::num::codegen_float_binop(fx, match intrinsic { - sym::fadd_fast => BinOp::Add, - sym::fsub_fast => BinOp::Sub, - sym::fmul_fast => BinOp::Mul, - sym::fdiv_fast => BinOp::Div, - sym::frem_fast => BinOp::Rem, - _ => unreachable!(), - }, x, y); + sym::fadd_fast | sym::fsub_fast | sym::fmul_fast | sym::fdiv_fast | sym::frem_fast => { + intrinsic_args!(fx, args => (x, y); intrinsic); + + let res = crate::num::codegen_float_binop( + fx, + match intrinsic { + sym::fadd_fast => BinOp::Add, + sym::fsub_fast => BinOp::Sub, + sym::fmul_fast => BinOp::Mul, + sym::fdiv_fast => BinOp::Div, + sym::frem_fast => BinOp::Rem, + _ => unreachable!(), + }, + x, + y, + ); ret.write_cvalue(fx, res); - }; - float_to_int_unchecked, (v f) { + } + sym::float_to_int_unchecked => { + intrinsic_args!(fx, args => (f); intrinsic); + let f = f.load_scalar(fx); + let res = crate::cast::clif_int_or_float_cast( fx, f, @@ -1103,66 +1217,74 @@ fn codegen_regular_intrinsic_call<'tcx>( type_sign(ret.layout().ty), ); ret.write_cvalue(fx, CValue::by_val(res, ret.layout())); - }; + } + + sym::raw_eq => { + intrinsic_args!(fx, args => (lhs_ref, rhs_ref); intrinsic); + let lhs_ref = lhs_ref.load_scalar(fx); + let rhs_ref = rhs_ref.load_scalar(fx); - raw_eq, (v lhs_ref, v rhs_ref) { let size = fx.layout_of(substs.type_at(0)).layout.size(); // FIXME add and use emit_small_memcmp - let is_eq_value = - if size == Size::ZERO { - // No bytes means they're trivially equal - fx.bcx.ins().iconst(types::I8, 1) - } else if let Some(clty) = size.bits().try_into().ok().and_then(Type::int) { - // Can't use `trusted` for these loads; they could be unaligned. - let mut flags = MemFlags::new(); - flags.set_notrap(); - let lhs_val = fx.bcx.ins().load(clty, flags, lhs_ref, 0); - let rhs_val = fx.bcx.ins().load(clty, flags, rhs_ref, 0); - let eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_val, rhs_val); - fx.bcx.ins().bint(types::I8, eq) - } else { - // Just call `memcmp` (like slices do in core) when the - // size is too large or it's not a power-of-two. - let signed_bytes = i64::try_from(size.bytes()).unwrap(); - let bytes_val = fx.bcx.ins().iconst(fx.pointer_type, signed_bytes); - let params = vec![AbiParam::new(fx.pointer_type); 3]; - let returns = vec![AbiParam::new(types::I32)]; - let args = &[lhs_ref, rhs_ref, bytes_val]; - let cmp = fx.lib_call("memcmp", params, returns, args)[0]; - let eq = fx.bcx.ins().icmp_imm(IntCC::Equal, cmp, 0); - fx.bcx.ins().bint(types::I8, eq) - }; + let is_eq_value = if size == Size::ZERO { + // No bytes means they're trivially equal + fx.bcx.ins().iconst(types::I8, 1) + } else if let Some(clty) = size.bits().try_into().ok().and_then(Type::int) { + // Can't use `trusted` for these loads; they could be unaligned. + let mut flags = MemFlags::new(); + flags.set_notrap(); + let lhs_val = fx.bcx.ins().load(clty, flags, lhs_ref, 0); + let rhs_val = fx.bcx.ins().load(clty, flags, rhs_ref, 0); + let eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_val, rhs_val); + fx.bcx.ins().bint(types::I8, eq) + } else { + // Just call `memcmp` (like slices do in core) when the + // size is too large or it's not a power-of-two. + let signed_bytes = i64::try_from(size.bytes()).unwrap(); + let bytes_val = fx.bcx.ins().iconst(fx.pointer_type, signed_bytes); + let params = vec![AbiParam::new(fx.pointer_type); 3]; + let returns = vec![AbiParam::new(types::I32)]; + let args = &[lhs_ref, rhs_ref, bytes_val]; + let cmp = fx.lib_call("memcmp", params, returns, args)[0]; + let eq = fx.bcx.ins().icmp_imm(IntCC::Equal, cmp, 0); + fx.bcx.ins().bint(types::I8, eq) + }; ret.write_cvalue(fx, CValue::by_val(is_eq_value, ret.layout())); - }; + } + + sym::const_allocate => { + intrinsic_args!(fx, args => (_size, _align); intrinsic); - const_allocate, (c _size, c _align) { // returns a null pointer at runtime. let null = fx.bcx.ins().iconst(fx.pointer_type, 0); ret.write_cvalue(fx, CValue::by_val(null, ret.layout())); - }; + } - const_deallocate, (c _ptr, c _size, c _align) { + sym::const_deallocate => { + intrinsic_args!(fx, args => (_ptr, _size, _align); intrinsic); // nop at runtime. - }; + } + + sym::black_box => { + intrinsic_args!(fx, args => (a); intrinsic); - black_box, (c a) { // FIXME implement black_box semantics ret.write_cvalue(fx, a); - }; + } // FIXME implement variadics in cranelift - va_copy, (o _dest, o _src) { + sym::va_copy | sym::va_arg | sym::va_end => { fx.tcx.sess.span_fatal( source_info.span, "Defining variadic functions is not yet supported by Cranelift", ); - }; - va_arg | va_end, (o _valist) { - fx.tcx.sess.span_fatal( - source_info.span, - "Defining variadic functions is not yet supported by Cranelift", - ); - }; + } + + _ => { + fx.tcx + .sess + .span_fatal(source_info.span, &format!("unsupported intrinsic {}", intrinsic)); + } } let ret_block = fx.get_block(destination.unwrap()); diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index d1ca9edf2e0..30e3d112594 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -25,13 +25,10 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( ret: CPlace<'tcx>, span: Span, ) { - intrinsic_match! { - fx, intrinsic, args, - _ => { - fx.tcx.sess.span_fatal(span, &format!("Unknown SIMD intrinsic {}", intrinsic)); - }; + match intrinsic { + sym::simd_cast => { + intrinsic_args!(fx, args => (a); intrinsic); - simd_cast, (c a) { if !a.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, a.layout().ty); return; @@ -45,9 +42,11 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( clif_int_or_float_cast(fx, lane, from_signed, ret_lane_clif_ty, to_signed) }); - }; + } + + sym::simd_eq | sym::simd_ne | sym::simd_lt | sym::simd_le | sym::simd_gt | sym::simd_ge => { + intrinsic_args!(fx, args => (x, y); intrinsic); - simd_eq | simd_ne | simd_lt | simd_le | simd_gt | simd_ge, (c x, c y) { if !x.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, x.layout().ty); return; @@ -57,7 +56,9 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( simd_pair_for_each_lane(fx, x, y, ret, &|fx, lane_ty, res_lane_ty, x_lane, y_lane| { let res_lane = match (lane_ty.kind(), intrinsic) { (ty::Uint(_), sym::simd_eq) => fx.bcx.ins().icmp(IntCC::Equal, x_lane, y_lane), - (ty::Uint(_), sym::simd_ne) => fx.bcx.ins().icmp(IntCC::NotEqual, x_lane, y_lane), + (ty::Uint(_), sym::simd_ne) => { + fx.bcx.ins().icmp(IntCC::NotEqual, x_lane, y_lane) + } (ty::Uint(_), sym::simd_lt) => { fx.bcx.ins().icmp(IntCC::UnsignedLessThan, x_lane, y_lane) } @@ -72,8 +73,12 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( } (ty::Int(_), sym::simd_eq) => fx.bcx.ins().icmp(IntCC::Equal, x_lane, y_lane), - (ty::Int(_), sym::simd_ne) => fx.bcx.ins().icmp(IntCC::NotEqual, x_lane, y_lane), - (ty::Int(_), sym::simd_lt) => fx.bcx.ins().icmp(IntCC::SignedLessThan, x_lane, y_lane), + (ty::Int(_), sym::simd_ne) => { + fx.bcx.ins().icmp(IntCC::NotEqual, x_lane, y_lane) + } + (ty::Int(_), sym::simd_lt) => { + fx.bcx.ins().icmp(IntCC::SignedLessThan, x_lane, y_lane) + } (ty::Int(_), sym::simd_le) => { fx.bcx.ins().icmp(IntCC::SignedLessThanOrEqual, x_lane, y_lane) } @@ -84,13 +89,21 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( fx.bcx.ins().icmp(IntCC::SignedGreaterThanOrEqual, x_lane, y_lane) } - (ty::Float(_), sym::simd_eq) => fx.bcx.ins().fcmp(FloatCC::Equal, x_lane, y_lane), - (ty::Float(_), sym::simd_ne) => fx.bcx.ins().fcmp(FloatCC::NotEqual, x_lane, y_lane), - (ty::Float(_), sym::simd_lt) => fx.bcx.ins().fcmp(FloatCC::LessThan, x_lane, y_lane), + (ty::Float(_), sym::simd_eq) => { + fx.bcx.ins().fcmp(FloatCC::Equal, x_lane, y_lane) + } + (ty::Float(_), sym::simd_ne) => { + fx.bcx.ins().fcmp(FloatCC::NotEqual, x_lane, y_lane) + } + (ty::Float(_), sym::simd_lt) => { + fx.bcx.ins().fcmp(FloatCC::LessThan, x_lane, y_lane) + } (ty::Float(_), sym::simd_le) => { fx.bcx.ins().fcmp(FloatCC::LessThanOrEqual, x_lane, y_lane) } - (ty::Float(_), sym::simd_gt) => fx.bcx.ins().fcmp(FloatCC::GreaterThan, x_lane, y_lane), + (ty::Float(_), sym::simd_gt) => { + fx.bcx.ins().fcmp(FloatCC::GreaterThan, x_lane, y_lane) + } (ty::Float(_), sym::simd_ge) => { fx.bcx.ins().fcmp(FloatCC::GreaterThanOrEqual, x_lane, y_lane) } @@ -103,10 +116,19 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let res_lane = fx.bcx.ins().bint(ty, res_lane); fx.bcx.ins().ineg(res_lane) }); - }; + } // simd_shuffle32(x: T, y: T, idx: [u32; 32]) -> U - _ if intrinsic.as_str().starts_with("simd_shuffle"), (c x, c y, o idx) { + _ if intrinsic.as_str().starts_with("simd_shuffle") => { + let (x, y, idx) = match args { + [x, y, idx] => (x, y, idx), + _ => { + bug!("wrong number of args for intrinsic {intrinsic}"); + } + }; + let x = codegen_operand(fx, x); + let y = codegen_operand(fx, y); + if !x.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, x.layout().ty); return; @@ -119,11 +141,13 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( // version of this intrinsic. let idx_ty = fx.monomorphize(idx.ty(fx.mir, fx.tcx)); match idx_ty.kind() { - ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { - len.try_eval_usize(fx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(|| { + ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => len + .try_eval_usize(fx.tcx, ty::ParamEnv::reveal_all()) + .unwrap_or_else(|| { span_bug!(span, "could not evaluate shuffle index array length") - }).try_into().unwrap() - } + }) + .try_into() + .unwrap(), _ => { fx.tcx.sess.span_err( span, @@ -154,24 +178,30 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let indexes = { use rustc_middle::mir::interpret::*; - let idx_const = crate::constant::mir_operand_get_const_val(fx, idx).expect("simd_shuffle* idx not const"); + let idx_const = crate::constant::mir_operand_get_const_val(fx, idx) + .expect("simd_shuffle* idx not const"); let idx_bytes = match idx_const { ConstValue::ByRef { alloc, offset } => { - let size = Size::from_bytes(4 * ret_lane_count /* size_of([u32; ret_lane_count]) */); + let size = Size::from_bytes( + 4 * ret_lane_count, /* size_of([u32; ret_lane_count]) */ + ); alloc.inner().get_bytes(fx, alloc_range(offset, size)).unwrap() } _ => unreachable!("{:?}", idx_const), }; - (0..ret_lane_count).map(|i| { - let i = usize::try_from(i).unwrap(); - let idx = rustc_middle::mir::interpret::read_target_uint( - fx.tcx.data_layout.endian, - &idx_bytes[4*i.. 4*i + 4], - ).expect("read_target_uint"); - u16::try_from(idx).expect("try_from u32") - }).collect::>() + (0..ret_lane_count) + .map(|i| { + let i = usize::try_from(i).unwrap(); + let idx = rustc_middle::mir::interpret::read_target_uint( + fx.tcx.data_layout.endian, + &idx_bytes[4 * i..4 * i + 4], + ) + .expect("read_target_uint"); + u16::try_from(idx).expect("try_from u32") + }) + .collect::>() }; for &idx in &indexes { @@ -187,43 +217,63 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let out_lane = ret.place_lane(fx, u64::try_from(out_idx).unwrap()); out_lane.write_cvalue(fx, in_lane); } - }; + } + + sym::simd_insert => { + let (base, idx, val) = match args { + [base, idx, val] => (base, idx, val), + _ => { + bug!("wrong number of args for intrinsic {intrinsic}"); + } + }; + let base = codegen_operand(fx, base); + let val = codegen_operand(fx, val); - simd_insert, (c base, o idx, c val) { // FIXME validate - let idx_const = if let Some(idx_const) = crate::constant::mir_operand_get_const_val(fx, idx) { + let idx_const = if let Some(idx_const) = + crate::constant::mir_operand_get_const_val(fx, idx) + { idx_const } else { - fx.tcx.sess.span_fatal( - span, - "Index argument for `simd_insert` is not a constant", - ); + fx.tcx.sess.span_fatal(span, "Index argument for `simd_insert` is not a constant"); }; - let idx = idx_const.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const)); + let idx = idx_const + .try_to_bits(Size::from_bytes(4 /* u32*/)) + .unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const)); let (lane_count, _lane_ty) = base.layout().ty.simd_size_and_type(fx.tcx); if idx >= lane_count.into() { - fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_insert] idx {} >= lane_count {}", idx, lane_count)); + fx.tcx.sess.span_fatal( + fx.mir.span, + &format!("[simd_insert] idx {} >= lane_count {}", idx, lane_count), + ); } ret.write_cvalue(fx, base); let ret_lane = ret.place_field(fx, mir::Field::new(idx.try_into().unwrap())); ret_lane.write_cvalue(fx, val); - }; + } + + sym::simd_extract => { + let (v, idx) = match args { + [v, idx] => (v, idx), + _ => { + bug!("wrong number of args for intrinsic {intrinsic}"); + } + }; + let v = codegen_operand(fx, v); - simd_extract, (c v, o idx) { if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); return; } - let idx_const = if let Some(idx_const) = crate::constant::mir_operand_get_const_val(fx, idx) { + let idx_const = if let Some(idx_const) = + crate::constant::mir_operand_get_const_val(fx, idx) + { idx_const } else { - fx.tcx.sess.span_warn( - span, - "Index argument for `simd_extract` is not a constant", - ); + fx.tcx.sess.span_warn(span, "Index argument for `simd_extract` is not a constant"); let res = crate::trap::trap_unimplemented_ret_value( fx, ret.layout(), @@ -233,89 +283,105 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( return; }; - let idx = idx_const.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const)); + let idx = idx_const + .try_to_bits(Size::from_bytes(4 /* u32*/)) + .unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const)); let (lane_count, _lane_ty) = v.layout().ty.simd_size_and_type(fx.tcx); if idx >= lane_count.into() { - fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_extract] idx {} >= lane_count {}", idx, lane_count)); + fx.tcx.sess.span_fatal( + fx.mir.span, + &format!("[simd_extract] idx {} >= lane_count {}", idx, lane_count), + ); } let ret_lane = v.value_lane(fx, idx.try_into().unwrap()); ret.write_cvalue(fx, ret_lane); - }; + } + + sym::simd_neg => { + intrinsic_args!(fx, args => (a); intrinsic); - simd_neg, (c a) { if !a.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, a.layout().ty); return; } - simd_for_each_lane(fx, a, ret, &|fx, lane_ty, _ret_lane_ty, lane| { - match lane_ty.kind() { + simd_for_each_lane( + fx, + a, + ret, + &|fx, lane_ty, _ret_lane_ty, lane| match lane_ty.kind() { ty::Int(_) => fx.bcx.ins().ineg(lane), ty::Float(_) => fx.bcx.ins().fneg(lane), _ => unreachable!(), - } - }); - }; - - simd_add | simd_sub | simd_mul | simd_div | simd_rem - | simd_shl | simd_shr | simd_and | simd_or | simd_xor, (c x, c y) { - if !x.layout().ty.is_simd() { - report_simd_type_validation_error(fx, intrinsic, span, x.layout().ty); - return; - } + }, + ); + } + + sym::simd_add + | sym::simd_sub + | sym::simd_mul + | sym::simd_div + | sym::simd_rem + | sym::simd_shl + | sym::simd_shr + | sym::simd_and + | sym::simd_or + | sym::simd_xor => { + intrinsic_args!(fx, args => (x, y); intrinsic); // FIXME use vector instructions when possible - simd_pair_for_each_lane(fx, x, y, ret, &|fx, lane_ty, _ret_lane_ty, x_lane, y_lane| match ( - lane_ty.kind(), - intrinsic, - ) { - (ty::Uint(_), sym::simd_add) => fx.bcx.ins().iadd(x_lane, y_lane), - (ty::Uint(_), sym::simd_sub) => fx.bcx.ins().isub(x_lane, y_lane), - (ty::Uint(_), sym::simd_mul) => fx.bcx.ins().imul(x_lane, y_lane), - (ty::Uint(_), sym::simd_div) => fx.bcx.ins().udiv(x_lane, y_lane), - (ty::Uint(_), sym::simd_rem) => fx.bcx.ins().urem(x_lane, y_lane), - - (ty::Int(_), sym::simd_add) => fx.bcx.ins().iadd(x_lane, y_lane), - (ty::Int(_), sym::simd_sub) => fx.bcx.ins().isub(x_lane, y_lane), - (ty::Int(_), sym::simd_mul) => fx.bcx.ins().imul(x_lane, y_lane), - (ty::Int(_), sym::simd_div) => fx.bcx.ins().sdiv(x_lane, y_lane), - (ty::Int(_), sym::simd_rem) => fx.bcx.ins().srem(x_lane, y_lane), - - (ty::Float(_), sym::simd_add) => fx.bcx.ins().fadd(x_lane, y_lane), - (ty::Float(_), sym::simd_sub) => fx.bcx.ins().fsub(x_lane, y_lane), - (ty::Float(_), sym::simd_mul) => fx.bcx.ins().fmul(x_lane, y_lane), - (ty::Float(_), sym::simd_div) => fx.bcx.ins().fdiv(x_lane, y_lane), - (ty::Float(FloatTy::F32), sym::simd_rem) => fx.lib_call( - "fmodf", - vec![AbiParam::new(types::F32), AbiParam::new(types::F32)], - vec![AbiParam::new(types::F32)], - &[x_lane, y_lane], - )[0], - (ty::Float(FloatTy::F64), sym::simd_rem) => fx.lib_call( - "fmod", - vec![AbiParam::new(types::F64), AbiParam::new(types::F64)], - vec![AbiParam::new(types::F64)], - &[x_lane, y_lane], - )[0], - - (ty::Uint(_), sym::simd_shl) => fx.bcx.ins().ishl(x_lane, y_lane), - (ty::Uint(_), sym::simd_shr) => fx.bcx.ins().ushr(x_lane, y_lane), - (ty::Uint(_), sym::simd_and) => fx.bcx.ins().band(x_lane, y_lane), - (ty::Uint(_), sym::simd_or) => fx.bcx.ins().bor(x_lane, y_lane), - (ty::Uint(_), sym::simd_xor) => fx.bcx.ins().bxor(x_lane, y_lane), - - (ty::Int(_), sym::simd_shl) => fx.bcx.ins().ishl(x_lane, y_lane), - (ty::Int(_), sym::simd_shr) => fx.bcx.ins().sshr(x_lane, y_lane), - (ty::Int(_), sym::simd_and) => fx.bcx.ins().band(x_lane, y_lane), - (ty::Int(_), sym::simd_or) => fx.bcx.ins().bor(x_lane, y_lane), - (ty::Int(_), sym::simd_xor) => fx.bcx.ins().bxor(x_lane, y_lane), - - _ => unreachable!(), + simd_pair_for_each_lane(fx, x, y, ret, &|fx, lane_ty, _ret_lane_ty, x_lane, y_lane| { + match (lane_ty.kind(), intrinsic) { + (ty::Uint(_), sym::simd_add) => fx.bcx.ins().iadd(x_lane, y_lane), + (ty::Uint(_), sym::simd_sub) => fx.bcx.ins().isub(x_lane, y_lane), + (ty::Uint(_), sym::simd_mul) => fx.bcx.ins().imul(x_lane, y_lane), + (ty::Uint(_), sym::simd_div) => fx.bcx.ins().udiv(x_lane, y_lane), + (ty::Uint(_), sym::simd_rem) => fx.bcx.ins().urem(x_lane, y_lane), + + (ty::Int(_), sym::simd_add) => fx.bcx.ins().iadd(x_lane, y_lane), + (ty::Int(_), sym::simd_sub) => fx.bcx.ins().isub(x_lane, y_lane), + (ty::Int(_), sym::simd_mul) => fx.bcx.ins().imul(x_lane, y_lane), + (ty::Int(_), sym::simd_div) => fx.bcx.ins().sdiv(x_lane, y_lane), + (ty::Int(_), sym::simd_rem) => fx.bcx.ins().srem(x_lane, y_lane), + + (ty::Float(_), sym::simd_add) => fx.bcx.ins().fadd(x_lane, y_lane), + (ty::Float(_), sym::simd_sub) => fx.bcx.ins().fsub(x_lane, y_lane), + (ty::Float(_), sym::simd_mul) => fx.bcx.ins().fmul(x_lane, y_lane), + (ty::Float(_), sym::simd_div) => fx.bcx.ins().fdiv(x_lane, y_lane), + (ty::Float(FloatTy::F32), sym::simd_rem) => fx.lib_call( + "fmodf", + vec![AbiParam::new(types::F32), AbiParam::new(types::F32)], + vec![AbiParam::new(types::F32)], + &[x_lane, y_lane], + )[0], + (ty::Float(FloatTy::F64), sym::simd_rem) => fx.lib_call( + "fmod", + vec![AbiParam::new(types::F64), AbiParam::new(types::F64)], + vec![AbiParam::new(types::F64)], + &[x_lane, y_lane], + )[0], + + (ty::Uint(_), sym::simd_shl) => fx.bcx.ins().ishl(x_lane, y_lane), + (ty::Uint(_), sym::simd_shr) => fx.bcx.ins().ushr(x_lane, y_lane), + (ty::Uint(_), sym::simd_and) => fx.bcx.ins().band(x_lane, y_lane), + (ty::Uint(_), sym::simd_or) => fx.bcx.ins().bor(x_lane, y_lane), + (ty::Uint(_), sym::simd_xor) => fx.bcx.ins().bxor(x_lane, y_lane), + + (ty::Int(_), sym::simd_shl) => fx.bcx.ins().ishl(x_lane, y_lane), + (ty::Int(_), sym::simd_shr) => fx.bcx.ins().sshr(x_lane, y_lane), + (ty::Int(_), sym::simd_and) => fx.bcx.ins().band(x_lane, y_lane), + (ty::Int(_), sym::simd_or) => fx.bcx.ins().bor(x_lane, y_lane), + (ty::Int(_), sym::simd_xor) => fx.bcx.ins().bxor(x_lane, y_lane), + + _ => unreachable!(), + } }); - }; + } + + sym::simd_fma => { + intrinsic_args!(fx, args => (a, b, c); intrinsic); - simd_fma, (c a, c b, c c) { if !a.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, a.layout().ty); return; @@ -333,16 +399,22 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let c_lane = c.value_lane(fx, lane); let res_lane = match lane_ty.kind() { - ty::Float(FloatTy::F32) => fx.easy_call("fmaf", &[a_lane, b_lane, c_lane], lane_ty), - ty::Float(FloatTy::F64) => fx.easy_call("fma", &[a_lane, b_lane, c_lane], lane_ty), + ty::Float(FloatTy::F32) => { + fx.easy_call("fmaf", &[a_lane, b_lane, c_lane], lane_ty) + } + ty::Float(FloatTy::F64) => { + fx.easy_call("fma", &[a_lane, b_lane, c_lane], lane_ty) + } _ => unreachable!(), }; ret.place_lane(fx, lane).write_cvalue(fx, res_lane); } - }; + } + + sym::simd_fmin | sym::simd_fmax => { + intrinsic_args!(fx, args => (x, y); intrinsic); - simd_fmin | simd_fmax, (c x, c y) { if !x.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, x.layout().ty); return; @@ -351,7 +423,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( // FIXME use vector instructions when possible simd_pair_for_each_lane(fx, x, y, ret, &|fx, lane_ty, _ret_lane_ty, x_lane, y_lane| { match lane_ty.kind() { - ty::Float(_) => {}, + ty::Float(_) => {} _ => unreachable!("{:?}", lane_ty), } match intrinsic { @@ -360,16 +432,21 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( _ => unreachable!(), } }); - }; + } + + sym::simd_round => { + intrinsic_args!(fx, args => (a); intrinsic); - simd_round, (c a) { if !a.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, a.layout().ty); return; } - simd_for_each_lane(fx, a, ret, &|fx, lane_ty, _ret_lane_ty, lane| { - match lane_ty.kind() { + simd_for_each_lane( + fx, + a, + ret, + &|fx, lane_ty, _ret_lane_ty, lane| match lane_ty.kind() { ty::Float(FloatTy::F32) => fx.lib_call( "roundf", vec![AbiParam::new(types::F32)], @@ -383,11 +460,13 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( &[lane], )[0], _ => unreachable!("{:?}", lane_ty), - } - }); - }; + }, + ); + } + + sym::simd_fabs | sym::simd_fsqrt | sym::simd_ceil | sym::simd_floor | sym::simd_trunc => { + intrinsic_args!(fx, args => (a); intrinsic); - simd_fabs | simd_fsqrt | simd_ceil | simd_floor | simd_trunc, (c a) { if !a.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, a.layout().ty); return; @@ -395,7 +474,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( simd_for_each_lane(fx, a, ret, &|fx, lane_ty, _ret_lane_ty, lane| { match lane_ty.kind() { - ty::Float(_) => {}, + ty::Float(_) => {} _ => unreachable!("{:?}", lane_ty), } match intrinsic { @@ -407,9 +486,12 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( _ => unreachable!(), } }); - }; + } + + sym::simd_reduce_add_ordered | sym::simd_reduce_add_unordered => { + intrinsic_args!(fx, args => (v, acc); intrinsic); + let acc = acc.load_scalar(fx); - simd_reduce_add_ordered | simd_reduce_add_unordered, (c v, v acc) { // FIXME there must be no acc param for integer vectors if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); @@ -423,9 +505,12 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( fx.bcx.ins().iadd(a, b) } }); - }; + } + + sym::simd_reduce_mul_ordered | sym::simd_reduce_mul_unordered => { + intrinsic_args!(fx, args => (v, acc); intrinsic); + let acc = acc.load_scalar(fx); - simd_reduce_mul_ordered | simd_reduce_mul_unordered, (c v, v acc) { // FIXME there must be no acc param for integer vectors if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); @@ -439,54 +524,66 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( fx.bcx.ins().imul(a, b) } }); - }; + } + + sym::simd_reduce_all => { + intrinsic_args!(fx, args => (v); intrinsic); - simd_reduce_all, (c v) { if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); return; } simd_reduce_bool(fx, v, ret, &|fx, a, b| fx.bcx.ins().band(a, b)); - }; + } + + sym::simd_reduce_any => { + intrinsic_args!(fx, args => (v); intrinsic); - simd_reduce_any, (c v) { if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); return; } simd_reduce_bool(fx, v, ret, &|fx, a, b| fx.bcx.ins().bor(a, b)); - }; + } + + sym::simd_reduce_and => { + intrinsic_args!(fx, args => (v); intrinsic); - simd_reduce_and, (c v) { if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); return; } simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| fx.bcx.ins().band(a, b)); - }; + } + + sym::simd_reduce_or => { + intrinsic_args!(fx, args => (v); intrinsic); - simd_reduce_or, (c v) { if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); return; } simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| fx.bcx.ins().bor(a, b)); - }; + } + + sym::simd_reduce_xor => { + intrinsic_args!(fx, args => (v); intrinsic); - simd_reduce_xor, (c v) { if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); return; } simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| fx.bcx.ins().bxor(a, b)); - }; + } + + sym::simd_reduce_min => { + intrinsic_args!(fx, args => (v); intrinsic); - simd_reduce_min, (c v) { if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); return; @@ -501,9 +598,11 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }; fx.bcx.ins().select(lt, a, b) }); - }; + } + + sym::simd_reduce_max => { + intrinsic_args!(fx, args => (v); intrinsic); - simd_reduce_max, (c v) { if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); return; @@ -518,9 +617,11 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }; fx.bcx.ins().select(gt, a, b) }); - }; + } + + sym::simd_select => { + intrinsic_args!(fx, args => (m, a, b); intrinsic); - simd_select, (c m, c a, c b) { if !m.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, m.layout().ty); return; @@ -540,15 +641,19 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let b_lane = b.value_lane(fx, lane).load_scalar(fx); let m_lane = fx.bcx.ins().icmp_imm(IntCC::Equal, m_lane, 0); - let res_lane = CValue::by_val(fx.bcx.ins().select(m_lane, b_lane, a_lane), lane_layout); + let res_lane = + CValue::by_val(fx.bcx.ins().select(m_lane, b_lane, a_lane), lane_layout); ret.place_lane(fx, lane).write_cvalue(fx, res_lane); } - }; + } // simd_saturating_* // simd_bitmask // simd_scatter // simd_gather + _ => { + fx.tcx.sess.span_fatal(span, &format!("Unknown SIMD intrinsic {}", intrinsic)); + } } } -- cgit 1.4.1-3-g733a5 From 152c851f891eaade1bbb3cc5d35d3e7b7412c7fa Mon Sep 17 00:00:00 2001 From: est31 Date: Wed, 27 Jul 2022 00:24:30 +0200 Subject: Make forward compatibility lint deprecated_cfg_attr_crate_type_name deny by default --- compiler/rustc_lint_defs/src/builtin.rs | 4 ++-- src/test/codegen/external-no-mangle-statics.rs | 5 ++--- .../cfg/future-compat-crate-attributes-using-cfg_attr.rs | 1 - .../future-compat-crate-attributes-using-cfg_attr.stderr | 15 +++++---------- 4 files changed, 9 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 39690851d1e..25897fdd0a0 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3068,7 +3068,7 @@ declare_lint! { /// /// ### Example /// - /// ```rust + /// ```rust,compile_fail /// #![cfg_attr(debug_assertions, crate_type = "lib")] /// ``` /// @@ -3088,7 +3088,7 @@ declare_lint! { /// rustc instead of `#![cfg_attr(..., crate_type = "...")]` and /// `--crate-name` instead of `#![cfg_attr(..., crate_name = "...")]`. pub DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, - Warn, + Deny, "detects usage of `#![cfg_attr(..., crate_type/crate_name = \"...\")]`", @future_incompatible = FutureIncompatibleInfo { reference: "issue #91632 ", diff --git a/src/test/codegen/external-no-mangle-statics.rs b/src/test/codegen/external-no-mangle-statics.rs index 6274434cd8f..c6ecb7aa96a 100644 --- a/src/test/codegen/external-no-mangle-statics.rs +++ b/src/test/codegen/external-no-mangle-statics.rs @@ -1,12 +1,11 @@ // revisions: lib staticlib // ignore-emscripten default visibility is hidden // compile-flags: -O +// [lib] compile-flags: --crate-type lib +// [staticlib] compile-flags: --crate-type staticlib // `#[no_mangle]`d static variables always have external linkage, i.e., no `internal` in their // definitions -#![cfg_attr(lib, crate_type = "lib")] -#![cfg_attr(staticlib, crate_type = "staticlib")] - // CHECK: @A = local_unnamed_addr constant #[no_mangle] static A: u8 = 0; diff --git a/src/test/ui/cfg/future-compat-crate-attributes-using-cfg_attr.rs b/src/test/ui/cfg/future-compat-crate-attributes-using-cfg_attr.rs index 6cb2ff9d813..1f23dadc432 100644 --- a/src/test/ui/cfg/future-compat-crate-attributes-using-cfg_attr.rs +++ b/src/test/ui/cfg/future-compat-crate-attributes-using-cfg_attr.rs @@ -1,7 +1,6 @@ // check-fail // compile-flags:--cfg foo -#![deny(warnings)] #![cfg_attr(foo, crate_type="bin")] //~^ERROR `crate_type` within //~| WARN this was previously accepted diff --git a/src/test/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr b/src/test/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr index 5609f8e9d9f..b52535ffdba 100644 --- a/src/test/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr +++ b/src/test/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr @@ -1,20 +1,15 @@ error: `crate_type` within an `#![cfg_attr] attribute is deprecated` - --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:5:18 + --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:4:18 | LL | #![cfg_attr(foo, crate_type="bin")] | ^^^^^^^^^^^^^^^^ | -note: the lint level is defined here - --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:4:9 - | -LL | #![deny(warnings)] - | ^^^^^^^^ - = note: `#[deny(deprecated_cfg_attr_crate_type_name)]` implied by `#[deny(warnings)]` + = note: `#[deny(deprecated_cfg_attr_crate_type_name)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #91632 error: `crate_name` within an `#![cfg_attr] attribute is deprecated` - --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:10:18 + --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:9:18 | LL | #![cfg_attr(foo, crate_name="bar")] | ^^^^^^^^^^^^^^^^ @@ -23,7 +18,7 @@ LL | #![cfg_attr(foo, crate_name="bar")] = note: for more information, see issue #91632 error: `crate_type` within an `#![cfg_attr] attribute is deprecated` - --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:5:18 + --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:4:18 | LL | #![cfg_attr(foo, crate_type="bin")] | ^^^^^^^^^^^^^^^^ @@ -32,7 +27,7 @@ LL | #![cfg_attr(foo, crate_type="bin")] = note: for more information, see issue #91632 error: `crate_name` within an `#![cfg_attr] attribute is deprecated` - --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:10:18 + --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:9:18 | LL | #![cfg_attr(foo, crate_name="bar")] | ^^^^^^^^^^^^^^^^ -- cgit 1.4.1-3-g733a5 From e34bb03197af68ef03a52ba0acbb9a44c958c253 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 27 Jul 2022 17:41:41 +0200 Subject: Rustup to rustc 1.64.0-nightly (4d6d601c8 2022-07-26) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 3ab395d89d5..ca1813a6ed0 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2022-07-25" +channel = "nightly-2022-07-27" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] -- cgit 1.4.1-3-g733a5 From e0697a309d8081310f9c94ae5f9fefde0924f670 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 28 Jul 2022 08:39:19 +0000 Subject: Move output argument from ArchiveBuilder::new to .build() --- src/archive.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/archive.rs b/src/archive.rs index c92c1051139..9d39b4aa661 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -19,7 +19,6 @@ enum ArchiveEntry { pub(crate) struct ArArchiveBuilder<'a> { sess: &'a Session, - dst: PathBuf, use_gnu_style_archive: bool, no_builtin_ranlib: bool, @@ -30,10 +29,9 @@ pub(crate) struct ArArchiveBuilder<'a> { } impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { - fn new(sess: &'a Session, output: &Path) -> Self { + fn new(sess: &'a Session) -> Self { ArArchiveBuilder { sess, - dst: output.to_path_buf(), use_gnu_style_archive: sess.target.archive_format == "gnu", // FIXME fix builtin ranlib on macOS no_builtin_ranlib: sess.target.is_like_osx, @@ -74,7 +72,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { Ok(()) } - fn build(mut self) -> bool { + fn build(mut self, output: &Path) -> bool { enum BuilderKind { Bsd(ar::Builder), Gnu(ar::GnuBuilder), @@ -163,7 +161,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { let mut builder = if self.use_gnu_style_archive { BuilderKind::Gnu( ar::GnuBuilder::new( - File::create(&self.dst).unwrap_or_else(|err| { + File::create(output).unwrap_or_else(|err| { sess.fatal(&format!( "error opening destination during archive building: {}", err @@ -178,7 +176,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { } else { BuilderKind::Bsd( ar::Builder::new( - File::create(&self.dst).unwrap_or_else(|err| { + File::create(output).unwrap_or_else(|err| { sess.fatal(&format!( "error opening destination during archive building: {}", err @@ -209,7 +207,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { // Run ranlib to be able to link the archive let status = std::process::Command::new(ranlib) - .arg(self.dst) + .arg(output) .status() .expect("Couldn't run ranlib"); -- cgit 1.4.1-3-g733a5 From 34b37e76ddebb1c231930b530a0ca1e8f3d86c7f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 28 Jul 2022 08:43:15 +0000 Subject: Inline inject_dll_import_lib --- src/archive.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/archive.rs b/src/archive.rs index 9d39b4aa661..e28c3813d3f 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -219,10 +219,6 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { any_members } - fn sess(&self) -> &Session { - self.sess - } - fn create_dll_import_lib( _sess: &Session, _lib_name: &str, -- cgit 1.4.1-3-g733a5 From 451817e48f7852017dd1ddc27bfa7709d74f646c Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 28 Jul 2022 09:07:49 +0000 Subject: Introduce an ArchiveBuilderBuilder This avoids monomorphizing all linker code for each codegen backend and will allow passing in extra information to the archive builder from the codegen backend. --- src/archive.rs | 60 ++++++++++++++++++++++++++++++++-------------------------- src/lib.rs | 2 +- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/src/archive.rs b/src/archive.rs index e28c3813d3f..b4c79096170 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -5,7 +5,7 @@ use std::fs::File; use std::io::{self, Read, Seek}; use std::path::{Path, PathBuf}; -use rustc_codegen_ssa::back::archive::ArchiveBuilder; +use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; use rustc_session::Session; use object::read::archive::ArchiveFile; @@ -17,6 +17,32 @@ enum ArchiveEntry { File(PathBuf), } +pub(crate) struct ArArchiveBuilderBuilder; + +impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { + fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box + 'a> { + Box::new(ArArchiveBuilder { + sess, + use_gnu_style_archive: sess.target.archive_format == "gnu", + // FIXME fix builtin ranlib on macOS + no_builtin_ranlib: sess.target.is_like_osx, + + src_archives: vec![], + entries: vec![], + }) + } + + fn create_dll_import_lib( + &self, + _sess: &Session, + _lib_name: &str, + _dll_imports: &[rustc_session::cstore::DllImport], + _tmpdir: &Path, + ) -> PathBuf { + bug!("creating dll imports is not supported"); + } +} + pub(crate) struct ArArchiveBuilder<'a> { sess: &'a Session, use_gnu_style_archive: bool, @@ -29,18 +55,6 @@ pub(crate) struct ArArchiveBuilder<'a> { } impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { - fn new(sess: &'a Session) -> Self { - ArArchiveBuilder { - sess, - use_gnu_style_archive: sess.target.archive_format == "gnu", - // FIXME fix builtin ranlib on macOS - no_builtin_ranlib: sess.target.is_like_osx, - - src_archives: vec![], - entries: vec![], - } - } - fn add_file(&mut self, file: &Path) { self.entries.push(( file.file_name().unwrap().to_str().unwrap().to_string().into_bytes(), @@ -48,10 +62,11 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { )); } - fn add_archive(&mut self, archive_path: &Path, mut skip: F) -> std::io::Result<()> - where - F: FnMut(&str) -> bool + 'static, - { + fn add_archive( + &mut self, + archive_path: &Path, + mut skip: Box bool + 'static>, + ) -> std::io::Result<()> { let read_cache = ReadCache::new(std::fs::File::open(&archive_path)?); let archive = ArchiveFile::parse(&read_cache).unwrap(); let archive_index = self.src_archives.len(); @@ -72,7 +87,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { Ok(()) } - fn build(mut self, output: &Path) -> bool { + fn build(mut self: Box, output: &Path) -> bool { enum BuilderKind { Bsd(ar::Builder), Gnu(ar::GnuBuilder), @@ -218,13 +233,4 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { any_members } - - fn create_dll_import_lib( - _sess: &Session, - _lib_name: &str, - _dll_imports: &[rustc_session::cstore::DllImport], - _tmpdir: &Path, - ) -> PathBuf { - bug!("creating dll imports is not supported"); - } } diff --git a/src/lib.rs b/src/lib.rs index 568bb20a3f4..bb0793b1deb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -226,7 +226,7 @@ impl CodegenBackend for CraneliftCodegenBackend { ) -> Result<(), ErrorGuaranteed> { use rustc_codegen_ssa::back::link::link_binary; - link_binary::>(sess, &codegen_results, outputs) + link_binary(sess, &crate::archive::ArArchiveBuilderBuilder, &codegen_results, outputs) } } -- cgit 1.4.1-3-g733a5 From 49e773183e504f4f73cfcb7dfd5a397b8c94be1e Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Thu, 28 Jul 2022 20:08:05 +0100 Subject: Update to cranelift 0.86 (#1250) --- Cargo.lock | 129 ++++++++++++++++++++++++++++++++----------------- Cargo.toml | 12 ++--- src/abi/pass_mode.rs | 2 +- src/common.rs | 2 +- src/intrinsics/mod.rs | 2 +- src/value_and_place.rs | 4 +- 6 files changed, 97 insertions(+), 54 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 532049c858d..352fd39a308 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,9 +15,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.56" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" +checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704" [[package]] name = "ar" @@ -50,18 +50,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.85.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "749d0d6022c9038dccf480bdde2a38d435937335bf2bb0f14e815d94517cdce8" +checksum = "529ffacce2249ac60edba2941672dfedf3d96558b415d0d8083cd007456e0f55" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.85.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94370cc7b37bf652ccd8bb8f09bd900997f7ccf97520edfc75554bb5c4abbea" +checksum = "427d105f617efc8cb55f8d036a7fded2e227892d8780b4985e5551f8d27c4a92" dependencies = [ "cranelift-bforest", "cranelift-codegen-meta", @@ -77,30 +77,30 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.85.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a3cea8fdab90e44018c5b9a1dfd460d8ee265ac354337150222a354628bdb6" +checksum = "551674bed85b838d45358e3eab4f0ffaa6790c70dc08184204b9a54b41cdb7d1" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.85.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac72f76f2698598951ab26d8c96eaa854810e693e7dd52523958b5909fde6b2" +checksum = "2b3a63ae57498c3eb495360944a33571754241e15e47e3bcae6082f40fec5866" [[package]] name = "cranelift-entity" -version = "0.85.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09eaeacfcd2356fe0e66b295e8f9d59fdd1ac3ace53ba50de14d628ec902f72d" +checksum = "11aa8aa624c72cc1c94ea3d0739fa61248260b5b14d3646f51593a88d67f3e6e" [[package]] name = "cranelift-frontend" -version = "0.85.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dba69c9980d5ffd62c18a2bde927855fcd7c8dc92f29feaf8636052662cbd99c" +checksum = "544ee8f4d1c9559c9aa6d46e7aaeac4a13856d620561094f35527356c7d21bd0" dependencies = [ "cranelift-codegen", "log", @@ -110,15 +110,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.85.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2920dc1e05cac40304456ed3301fde2c09bd6a9b0210bcfa2f101398d628d5b" +checksum = "ed16b14363d929b8c37e3c557d0a7396791b383ecc302141643c054343170aad" [[package]] name = "cranelift-jit" -version = "0.85.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c3c5ed067f2c81577e431f3039148a9c187b33cc79e0d1731fede27d801ec56" +checksum = "0308e7418208639fb96c1a3dc04955fa41c4bc92dfce9106635185f71d5caf46" dependencies = [ "anyhow", "cranelift-codegen", @@ -129,14 +129,14 @@ dependencies = [ "log", "region", "target-lexicon", - "winapi", + "windows-sys", ] [[package]] name = "cranelift-module" -version = "0.85.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee6784303bf9af235237a4885f7417e09a35df896d38ea969a0081064b3ede4" +checksum = "76979aac10dbcf0c222cd5902565bc93597ac30bbe9d879a2aa5f2402d1561f2" dependencies = [ "anyhow", "cranelift-codegen", @@ -144,9 +144,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.85.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04dfa45f9b2a6f587c564d6b63388e00cd6589d2df6ea2758cf79e1a13285e6" +checksum = "51617cf8744634f2ed3c989c3c40cd6444f63377c6d994adab0d85807f3eb682" dependencies = [ "cranelift-codegen", "libc", @@ -155,9 +155,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.85.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf38b2c505db749276793116c0cb30bd096206c7810e471677a453134881881" +checksum = "50e649a13f3951ad3b8cb13a3a774481c12159a98eb386b04583573c57d7cf56" dependencies = [ "anyhow", "cranelift-codegen", @@ -187,9 +187,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "libc", @@ -198,9 +198,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.26.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" dependencies = [ "indexmap", ] @@ -248,9 +248,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] @@ -266,9 +266,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "object" @@ -284,15 +284,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.10.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" +checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" [[package]] name = "regalloc2" -version = "0.2.3" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a8d23b35d7177df3b9d31ed8a9ab4bf625c668be77a319d4f5efd4a5257701c" +checksum = "76ff2e57a7d050308b3fde0f707aa240b491b190e3855f212860f11bb3af4205" dependencies = [ "fxhash", "log", @@ -340,15 +340,15 @@ checksum = "03b634d87b960ab1a38c4fe143b508576f075e7c978bfad18217645ebfdfa2ec" [[package]] name = "smallvec" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc88c725d61fc6c3132893370cac4a0200e3fedf5da8331c570664b1987f5ca2" +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "target-lexicon" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7fa7e55043acb85fca6b3c01485a2eeb6b69c5d21002e273c79e465f43b7ac1" +checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1" [[package]] name = "version_check" @@ -358,9 +358,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "winapi" @@ -383,3 +383,46 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" diff --git a/Cargo.toml b/Cargo.toml index 61e977e3e69..3f343a49e0c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.85.3", features = ["unwind", "all-arch"] } -cranelift-frontend = "0.85.3" -cranelift-module = "0.85.3" -cranelift-native = "0.85.3" -cranelift-jit = { version = "0.85.3", optional = true } -cranelift-object = "0.85.3" +cranelift-codegen = { version = "0.86.1", features = ["unwind", "all-arch"] } +cranelift-frontend = "0.86.1" +cranelift-module = "0.86.1" +cranelift-native = "0.86.1" +cranelift-jit = { version = "0.86.1", optional = true } +cranelift-object = "0.86.1" target-lexicon = "0.12.0" gimli = { version = "0.26.0", default-features = false, features = ["write"]} object = { version = "0.28.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } diff --git a/src/abi/pass_mode.rs b/src/abi/pass_mode.rs index 6c10baa53d4..2f8c697bd1e 100644 --- a/src/abi/pass_mode.rs +++ b/src/abi/pass_mode.rs @@ -23,7 +23,7 @@ fn reg_to_abi_param(reg: Reg) -> AbiParam { (RegKind::Integer, 9..=16) => types::I128, (RegKind::Float, 4) => types::F32, (RegKind::Float, 8) => types::F64, - (RegKind::Vector, size) => types::I8.by(u16::try_from(size).unwrap()).unwrap(), + (RegKind::Vector, size) => types::I8.by(u32::try_from(size).unwrap()).unwrap(), _ => unreachable!("{:?}", reg), }; AbiParam::new(clif_ty) diff --git a/src/common.rs b/src/common.rs index f9dc1b5169e..fc4953cea6f 100644 --- a/src/common.rs +++ b/src/common.rs @@ -74,7 +74,7 @@ fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option unreachable!(), }; - match scalar_to_clif_type(tcx, element).by(u16::try_from(count).unwrap()) { + match scalar_to_clif_type(tcx, element).by(u32::try_from(count).unwrap()) { // Cranelift currently only implements icmp for 128bit vectors. Some(vector_ty) if vector_ty.bits() == 128 => vector_ty, _ => return None, diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index b2a83e1d4eb..f552c13958d 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -53,7 +53,7 @@ pub(crate) fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx _ => unreachable!(), }; - match scalar_to_clif_type(tcx, element).by(u16::try_from(count).unwrap()) { + match scalar_to_clif_type(tcx, element).by(u32::try_from(count).unwrap()) { // Cranelift currently only implements icmp for 128bit vectors. Some(vector_ty) if vector_ty.bits() == 128 => Some(vector_ty), _ => None, diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 45ae2bd8f07..e48d095d139 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -122,7 +122,7 @@ impl<'tcx> CValue<'tcx> { let clif_ty = match layout.abi { Abi::Scalar(scalar) => scalar_to_clif_type(fx.tcx, scalar), Abi::Vector { element, count } => scalar_to_clif_type(fx.tcx, element) - .by(u16::try_from(count).unwrap()) + .by(u32::try_from(count).unwrap()) .unwrap(), _ => unreachable!("{:?}", layout.ty), }; @@ -519,7 +519,7 @@ impl<'tcx> CPlace<'tcx> { if let ty::Array(element, len) = dst_layout.ty.kind() { // Can only happen for vector types let len = - u16::try_from(len.eval_usize(fx.tcx, ParamEnv::reveal_all())).unwrap(); + u32::try_from(len.eval_usize(fx.tcx, ParamEnv::reveal_all())).unwrap(); let vector_ty = fx.clif_type(*element).unwrap().by(len).unwrap(); let data = match from.0 { -- cgit 1.4.1-3-g733a5 From 6fd1660650c8bf8d00ccdf53506f3eedf67f40fd Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Fri, 29 Jul 2022 08:39:18 +0100 Subject: Add Windows build artifacts to .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 5aeaf3a1788..38dd5b26063 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ perf.data.old *.string* /y.bin /y.bin.dSYM +/y.exe +/y.pdb /build /build_sysroot/sysroot_src /build_sysroot/compiler-builtins -- cgit 1.4.1-3-g733a5 From e896228ef30b0df332f3297689f8116683d88dec Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 5 Jul 2022 08:26:12 +0000 Subject: Update tracing to 0.1.31 --- Cargo.lock | 21 ++++++++++++++------- src/tools/tidy/src/deps.rs | 1 + 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 58c3982de23..68c55bfc43f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5394,9 +5394,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.29" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" +checksum = "f6c650a8ef0cd2dd93736f033d21cbd1224c5a967aa0c258d00fcf7dafef9b9f" dependencies = [ "cfg-if 1.0.0", "pin-project-lite", @@ -5406,9 +5406,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.18" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e" +checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" dependencies = [ "proc-macro2", "quote", @@ -5417,11 +5417,12 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.21" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" +checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7" dependencies = [ - "lazy_static", + "once_cell", + "valuable", ] [[package]] @@ -5757,6 +5758,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d" +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "vcpkg" version = "0.2.10" diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 333f85f6d62..a582ed1325f 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -247,6 +247,7 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[ "unicode-width", "unicode-xid", "vcpkg", + "valuable", "version_check", "wasi", "winapi", -- cgit 1.4.1-3-g733a5 From 9f44a635700acced0c00acdeb42efa8ff1dcb9ca Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 5 Jul 2022 13:08:52 +0000 Subject: tracing 0.1.33 --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 68c55bfc43f..ca8da9ee36e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5394,9 +5394,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.31" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6c650a8ef0cd2dd93736f033d21cbd1224c5a967aa0c258d00fcf7dafef9b9f" +checksum = "80b9fa4360528139bc96100c160b7ae879f5567f49f1782b0b02035b0358ebf3" dependencies = [ "cfg-if 1.0.0", "pin-project-lite", -- cgit 1.4.1-3-g733a5 From 6a0511d3d563ee90bd2b1cf9e6f903766046cec8 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 5 Jul 2022 19:25:10 +0000 Subject: tracing 0.1.32 --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ca8da9ee36e..6908e9f1120 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5394,9 +5394,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.33" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80b9fa4360528139bc96100c160b7ae879f5567f49f1782b0b02035b0358ebf3" +checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f" dependencies = [ "cfg-if 1.0.0", "pin-project-lite", -- cgit 1.4.1-3-g733a5 From 92bc9db8812aaa5913a01247ef3e1129e8f3d98e Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 6 Jul 2022 07:10:22 +0000 Subject: never inline the only thing that calls a query, which could hit the instrument path --- compiler/rustc_trait_selection/src/traits/fulfill.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 556ef466cd1..d840677f1ca 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -597,6 +597,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { } } + #[inline(never)] fn process_backedge<'c, I>( &mut self, cycle: I, -- cgit 1.4.1-3-g733a5 From a4375cb2920835cfefaadaea3cf54025a463a214 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 6 Jul 2022 12:39:32 +0000 Subject: Bump tracing to 0.1.35 --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6908e9f1120..f0e589ffa6e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5394,9 +5394,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.32" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f" +checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" dependencies = [ "cfg-if 1.0.0", "pin-project-lite", -- cgit 1.4.1-3-g733a5 From c6558c0bc71024b8aca1db317c15cdf701d917d8 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 29 Jul 2022 20:04:28 +0400 Subject: Recover keywords in bounds For example, this fixes a error for `impl fn()` (notice the capitalization) --- compiler/rustc_parse/src/parser/ty.rs | 8 +++++++- src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs | 3 ++- src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr | 12 +++++++++--- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 31b40a83e60..b76ba8ff2d9 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -640,7 +640,13 @@ impl<'a> Parser<'a> { let mut bounds = Vec::new(); let mut negative_bounds = Vec::new(); - while self.can_begin_bound() || self.token.is_keyword(kw::Dyn) { + while self.can_begin_bound() + // Continue even if we find a keyword. + // This is necessary for error recover on, for example, `impl fn()`. + // + // The only keyword that can go after generic bounds is `where`, so stop if it's it. + || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where)) + { if self.token.is_keyword(kw::Dyn) { // Account for `&dyn Trait + dyn Other`. self.struct_span_err(self.token.span, "invalid `dyn` keyword") diff --git a/src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs index e8b26154549..e0d3e0b497b 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs @@ -3,4 +3,5 @@ #![feature(const_trait_impl)] struct S; -//~^ ERROR expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, `~`, lifetime, or path +//~^ ERROR expected identifier, found keyword `const` +//~| ERROR expected one of `(`, `+`, `,`, `::`, `<`, `=`, or `>`, found `Tr` diff --git a/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr index b6b77ac4a2f..243f0979509 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr @@ -1,8 +1,14 @@ -error: expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, `~`, lifetime, or path, found keyword `const` +error: expected identifier, found keyword `const` --> $DIR/without-tilde.rs:5:13 | LL | struct S; - | ^^^^^ expected one of 10 possible tokens + | ^^^^^ expected identifier, found keyword -error: aborting due to previous error +error: expected one of `(`, `+`, `,`, `::`, `<`, `=`, or `>`, found `Tr` + --> $DIR/without-tilde.rs:5:19 + | +LL | struct S; + | ^^ expected one of 7 possible tokens + +error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From 798016c2df3a15da739e8c6d0968ba0f7b54e303 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 29 Jul 2022 21:59:08 +0400 Subject: add a silly test for keywords in trait bounds recovery --- src/test/ui/parser/kw-in-trait-bounds.rs | 47 ++++++++ src/test/ui/parser/kw-in-trait-bounds.stderr | 171 +++++++++++++++++++++++++++ 2 files changed, 218 insertions(+) create mode 100644 src/test/ui/parser/kw-in-trait-bounds.rs create mode 100644 src/test/ui/parser/kw-in-trait-bounds.stderr diff --git a/src/test/ui/parser/kw-in-trait-bounds.rs b/src/test/ui/parser/kw-in-trait-bounds.rs new file mode 100644 index 00000000000..fa037e5937d --- /dev/null +++ b/src/test/ui/parser/kw-in-trait-bounds.rs @@ -0,0 +1,47 @@ +// edition:2018 + +fn _f(_: impl fn(), _: &dyn fn()) +//~^ ERROR expected identifier, found keyword `fn` +//~| ERROR expected identifier, found keyword `fn` +//~| ERROR expected identifier, found keyword `fn` +//~| ERROR cannot find trait `r#fn` in this scope +//~| ERROR cannot find trait `r#fn` in this scope +//~| ERROR cannot find trait `r#fn` in this scope +//~| HELP a trait with a similar name exists +//~| HELP a trait with a similar name exists +//~| HELP a trait with a similar name exists +//~| HELP escape `fn` to use it as an identifier +//~| HELP escape `fn` to use it as an identifier +//~| HELP escape `fn` to use it as an identifier +where +G: fn(), + //~^ ERROR expected identifier, found keyword `fn` + //~| ERROR cannot find trait `r#fn` in this scope + //~| HELP a trait with a similar name exists + //~| HELP escape `fn` to use it as an identifier +{} + +fn _g(_: impl struct, _: &dyn struct) +//~^ ERROR expected identifier, found keyword `struct` +//~| ERROR expected identifier, found keyword `struct` +//~| ERROR expected identifier, found keyword `struct` +//~| ERROR cannot find trait `r#struct` in this scope +//~| ERROR cannot find trait `r#struct` in this scope +//~| ERROR cannot find trait `r#struct` in this scope +//~| HELP a trait with a similar name exists +//~| HELP a trait with a similar name exists +//~| HELP a trait with a similar name exists +//~| HELP escape `struct` to use it as an identifier +//~| HELP escape `struct` to use it as an identifier +//~| HELP escape `struct` to use it as an identifier +where + B: struct, + //~^ ERROR expected identifier, found keyword `struct` + //~| ERROR cannot find trait `r#struct` in this scope + //~| HELP a trait with a similar name exists + //~| HELP escape `struct` to use it as an identifier +{} + +trait Struct {} + +fn main() {} diff --git a/src/test/ui/parser/kw-in-trait-bounds.stderr b/src/test/ui/parser/kw-in-trait-bounds.stderr new file mode 100644 index 00000000000..28196c7ce2d --- /dev/null +++ b/src/test/ui/parser/kw-in-trait-bounds.stderr @@ -0,0 +1,171 @@ +error: expected identifier, found keyword `fn` + --> $DIR/kw-in-trait-bounds.rs:3:10 + | +LL | fn _f(_: impl fn(), _: &dyn fn()) + | ^^ expected identifier, found keyword + | +help: escape `fn` to use it as an identifier + | +LL | fn _f(_: impl fn(), _: &dyn fn()) + | ++ + +error: expected identifier, found keyword `fn` + --> $DIR/kw-in-trait-bounds.rs:3:27 + | +LL | fn _f(_: impl fn(), _: &dyn fn()) + | ^^ expected identifier, found keyword + | +help: escape `fn` to use it as an identifier + | +LL | fn _f(_: impl r#fn(), _: &dyn fn()) + | ++ + +error: expected identifier, found keyword `fn` + --> $DIR/kw-in-trait-bounds.rs:3:41 + | +LL | fn _f(_: impl fn(), _: &dyn fn()) + | ^^ expected identifier, found keyword + | +help: escape `fn` to use it as an identifier + | +LL | fn _f(_: impl fn(), _: &dyn r#fn()) + | ++ + +error: expected identifier, found keyword `fn` + --> $DIR/kw-in-trait-bounds.rs:17:4 + | +LL | G: fn(), + | ^^ expected identifier, found keyword + | +help: escape `fn` to use it as an identifier + | +LL | G: r#fn(), + | ++ + +error: expected identifier, found keyword `struct` + --> $DIR/kw-in-trait-bounds.rs:24:10 + | +LL | fn _g(_: impl struct, _: &dyn struct) + | ^^^^^^ expected identifier, found keyword + | +help: escape `struct` to use it as an identifier + | +LL | fn _g(_: impl struct, _: &dyn struct) + | ++ + +error: expected identifier, found keyword `struct` + --> $DIR/kw-in-trait-bounds.rs:24:29 + | +LL | fn _g(_: impl struct, _: &dyn struct) + | ^^^^^^ expected identifier, found keyword + | +help: escape `struct` to use it as an identifier + | +LL | fn _g(_: impl r#struct, _: &dyn struct) + | ++ + +error: expected identifier, found keyword `struct` + --> $DIR/kw-in-trait-bounds.rs:24:45 + | +LL | fn _g(_: impl struct, _: &dyn struct) + | ^^^^^^ expected identifier, found keyword + | +help: escape `struct` to use it as an identifier + | +LL | fn _g(_: impl struct, _: &dyn r#struct) + | ++ + +error: expected identifier, found keyword `struct` + --> $DIR/kw-in-trait-bounds.rs:38:8 + | +LL | B: struct, + | ^^^^^^ expected identifier, found keyword + | +help: escape `struct` to use it as an identifier + | +LL | B: r#struct, + | ++ + +error[E0405]: cannot find trait `r#fn` in this scope + --> $DIR/kw-in-trait-bounds.rs:3:10 + | +LL | fn _f(_: impl fn(), _: &dyn fn()) + | ^^ help: a trait with a similar name exists (notice the capitalization): `Fn` + | + ::: $SRC_DIR/core/src/ops/function.rs:LL:COL + | +LL | pub trait Fn: FnMut { + | ------------------------------- similarly named trait `Fn` defined here + +error[E0405]: cannot find trait `r#fn` in this scope + --> $DIR/kw-in-trait-bounds.rs:17:4 + | +LL | G: fn(), + | ^^ help: a trait with a similar name exists (notice the capitalization): `Fn` + | + ::: $SRC_DIR/core/src/ops/function.rs:LL:COL + | +LL | pub trait Fn: FnMut { + | ------------------------------- similarly named trait `Fn` defined here + +error[E0405]: cannot find trait `r#fn` in this scope + --> $DIR/kw-in-trait-bounds.rs:3:27 + | +LL | fn _f(_: impl fn(), _: &dyn fn()) + | ^^ help: a trait with a similar name exists (notice the capitalization): `Fn` + | + ::: $SRC_DIR/core/src/ops/function.rs:LL:COL + | +LL | pub trait Fn: FnMut { + | ------------------------------- similarly named trait `Fn` defined here + +error[E0405]: cannot find trait `r#fn` in this scope + --> $DIR/kw-in-trait-bounds.rs:3:41 + | +LL | fn _f(_: impl fn(), _: &dyn fn()) + | ^^ help: a trait with a similar name exists (notice the capitalization): `Fn` + | + ::: $SRC_DIR/core/src/ops/function.rs:LL:COL + | +LL | pub trait Fn: FnMut { + | ------------------------------- similarly named trait `Fn` defined here + +error[E0405]: cannot find trait `r#struct` in this scope + --> $DIR/kw-in-trait-bounds.rs:24:10 + | +LL | fn _g(_: impl struct, _: &dyn struct) + | ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct` +... +LL | trait Struct {} + | ------------ similarly named trait `Struct` defined here + +error[E0405]: cannot find trait `r#struct` in this scope + --> $DIR/kw-in-trait-bounds.rs:38:8 + | +LL | B: struct, + | ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct` +... +LL | trait Struct {} + | ------------ similarly named trait `Struct` defined here + +error[E0405]: cannot find trait `r#struct` in this scope + --> $DIR/kw-in-trait-bounds.rs:24:29 + | +LL | fn _g(_: impl struct, _: &dyn struct) + | ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct` +... +LL | trait Struct {} + | ------------ similarly named trait `Struct` defined here + +error[E0405]: cannot find trait `r#struct` in this scope + --> $DIR/kw-in-trait-bounds.rs:24:45 + | +LL | fn _g(_: impl struct, _: &dyn struct) + | ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct` +... +LL | trait Struct {} + | ------------ similarly named trait `Struct` defined here + +error: aborting due to 16 previous errors + +For more information about this error, try `rustc --explain E0405`. -- cgit 1.4.1-3-g733a5 From fb12f40f3b157b0f7dafe393b09bbdcf2e156c11 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 30 Jul 2022 00:41:39 +0000 Subject: Do not leak type variables from opaque type relation --- compiler/rustc_infer/src/infer/sub.rs | 17 ++++++++++++++--- src/test/ui/impl-trait/issue-99914.rs | 13 +++++++++++++ src/test/ui/impl-trait/issue-99914.stderr | 21 +++++++++++++++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/impl-trait/issue-99914.rs create mode 100644 src/test/ui/impl-trait/issue-99914.stderr diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index b27571275b7..b7eab5d4328 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -4,6 +4,7 @@ use super::SubregionOrigin; use crate::infer::combine::ConstEquateRelation; use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::traits::Obligation; +use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::TyVar; @@ -141,17 +142,27 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { Ok(infcx.tcx.mk_ty_var(var)) }; let (a, b) = if self.a_is_expected { (a, b) } else { (b, a) }; - let (a, b) = match (a.kind(), b.kind()) { + let (ga, gb) = match (a.kind(), b.kind()) { (&ty::Opaque(..), _) => (a, generalize(b, true)?), (_, &ty::Opaque(..)) => (generalize(a, false)?, b), _ => unreachable!(), }; self.fields.obligations.extend( infcx - .handle_opaque_type(a, b, true, &self.fields.trace.cause, self.param_env())? + .handle_opaque_type(ga, gb, true, &self.fields.trace.cause, self.param_env()) + // Don't leak any generalized type variables out of this + // subtyping relation in the case of a type error. + .map_err(|err| { + let (ga, gb) = self.fields.infcx.resolve_vars_if_possible((ga, gb)); + if let TypeError::Sorts(sorts) = err && sorts.expected == ga && sorts.found == gb { + TypeError::Sorts(ExpectedFound { expected: a, found: b }) + } else { + err + } + })? .obligations, ); - Ok(a) + Ok(ga) } _ => { diff --git a/src/test/ui/impl-trait/issue-99914.rs b/src/test/ui/impl-trait/issue-99914.rs new file mode 100644 index 00000000000..4324a0229a6 --- /dev/null +++ b/src/test/ui/impl-trait/issue-99914.rs @@ -0,0 +1,13 @@ +// edition:2021 + +fn main() {} + +struct Error; +struct Okay; + +fn foo(t: Result) { + t.and_then(|t| -> _ { bar(t) }); + //~^ ERROR mismatched types +} + +async fn bar(t: Okay) {} diff --git a/src/test/ui/impl-trait/issue-99914.stderr b/src/test/ui/impl-trait/issue-99914.stderr new file mode 100644 index 00000000000..074d5d58d9a --- /dev/null +++ b/src/test/ui/impl-trait/issue-99914.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/issue-99914.rs:9:27 + | +LL | t.and_then(|t| -> _ { bar(t) }); + | ^^^^^^ expected enum `Result`, found opaque type + | +note: while checking the return type of the `async fn` + --> $DIR/issue-99914.rs:13:23 + | +LL | async fn bar(t: Okay) {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected enum `Result<_, Error>` + found opaque type `impl Future` +help: try wrapping the expression in `Ok` + | +LL | t.and_then(|t| -> _ { Ok(bar(t)) }); + | +++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. -- cgit 1.4.1-3-g733a5 From 3ce83dc4697ad6698ae45e6cdefa8ae3894c57a3 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 10:32:54 +0100 Subject: Move test.sh to y.rs test --- .cirrus.yml | 2 +- .github/workflows/main.yml | 2 +- build_system/build_backend.rs | 5 +- build_system/build_sysroot.rs | 12 +- build_system/mod.rs | 42 +++- build_system/prepare.rs | 3 +- build_system/tests.rs | 504 ++++++++++++++++++++++++++++++++++++++++++ build_system/utils.rs | 24 +- config.txt | 33 +++ scripts/tests.sh | 203 ----------------- test.sh | 13 -- 11 files changed, 605 insertions(+), 238 deletions(-) create mode 100644 build_system/tests.rs delete mode 100755 scripts/tests.sh delete mode 100755 test.sh diff --git a/.cirrus.yml b/.cirrus.yml index 61da6a2491c..732edd66196 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -22,4 +22,4 @@ task: - # Reduce amount of benchmark runs as they are slow - export COMPILE_RUNS=2 - export RUN_RUNS=2 - - ./test.sh + - ./y.rs test diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index aa556a21bf8..a36c570ddc8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -103,7 +103,7 @@ jobs: # Enable extra checks export CG_CLIF_ENABLE_VERIFIER=1 - ./test.sh + ./y.rs test - name: Package prebuilt cg_clif run: tar cvfJ cg_clif.tar.xz build diff --git a/build_system/build_backend.rs b/build_system/build_backend.rs index 48faec8bc4b..04f8be6f820 100644 --- a/build_system/build_backend.rs +++ b/build_system/build_backend.rs @@ -1,12 +1,11 @@ use std::env; -use std::path::{Path, PathBuf}; use std::process::Command; pub(crate) fn build_backend( channel: &str, host_triple: &str, use_unstable_features: bool, -) -> PathBuf { +) { let mut cmd = Command::new("cargo"); cmd.arg("build").arg("--target").arg(host_triple); @@ -38,6 +37,4 @@ pub(crate) fn build_backend( eprintln!("[BUILD] rustc_codegen_cranelift"); super::utils::spawn_and_wait(cmd); - - Path::new("target").join(host_triple).join(channel) } diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index 16cce83dd9c..dddd5a673c5 100644 --- a/build_system/build_sysroot.rs +++ b/build_system/build_sysroot.rs @@ -10,10 +10,12 @@ pub(crate) fn build_sysroot( channel: &str, sysroot_kind: SysrootKind, target_dir: &Path, - cg_clif_build_dir: PathBuf, + cg_clif_build_dir: &Path, host_triple: &str, target_triple: &str, ) { + eprintln!("[BUILD] sysroot {:?}", sysroot_kind); + if target_dir.exists() { fs::remove_dir_all(target_dir).unwrap(); } @@ -35,11 +37,17 @@ pub(crate) fn build_sysroot( // Build and copy rustc and cargo wrappers for wrapper in ["rustc-clif", "cargo-clif"] { + let wrapper_name = if cfg!(windows) { + format!("{wrapper}.exe") + } else { + wrapper.to_string() + }; + let mut build_cargo_wrapper_cmd = Command::new("rustc"); build_cargo_wrapper_cmd .arg(PathBuf::from("scripts").join(format!("{wrapper}.rs"))) .arg("-o") - .arg(target_dir.join(wrapper)) + .arg(target_dir.join(wrapper_name)) .arg("-g"); spawn_and_wait(build_cargo_wrapper_cmd); } diff --git a/build_system/mod.rs b/build_system/mod.rs index b897b7fbacf..d1f8ad3e817 100644 --- a/build_system/mod.rs +++ b/build_system/mod.rs @@ -1,5 +1,5 @@ use std::env; -use std::path::PathBuf; +use std::path::{PathBuf, Path}; use std::process; mod build_backend; @@ -8,6 +8,7 @@ mod config; mod prepare; mod rustc_info; mod utils; +mod tests; fn usage() { eprintln!("Usage:"); @@ -15,6 +16,9 @@ fn usage() { eprintln!( " ./y.rs build [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]" ); + eprintln!( + " ./y.rs test [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]" + ); } macro_rules! arg_error { @@ -25,11 +29,13 @@ macro_rules! arg_error { }}; } +#[derive(PartialEq, Debug)] enum Command { Build, + Test, } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub(crate) enum SysrootKind { None, Clif, @@ -52,6 +58,7 @@ pub fn main() { process::exit(0); } Some("build") => Command::Build, + Some("test") => Command::Test, Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), Some(command) => arg_error!("Unknown command {}", command), None => { @@ -115,14 +122,27 @@ pub fn main() { process::exit(1); } - let cg_clif_build_dir = + let cg_clif_build_dir = Path::new("target").join(&host_triple).join(&channel); + + if command == Command::Test { + // TODO: Should we also build_backend here? + tests::run_tests( + channel, + sysroot_kind, + &target_dir, + &cg_clif_build_dir, + &host_triple, + &target_triple, + ).expect("Failed to run tests"); + } else { build_backend::build_backend(channel, &host_triple, use_unstable_features); - build_sysroot::build_sysroot( - channel, - sysroot_kind, - &target_dir, - cg_clif_build_dir, - &host_triple, - &target_triple, - ); + build_sysroot::build_sysroot( + channel, + sysroot_kind, + &target_dir, + &cg_clif_build_dir, + &host_triple, + &target_triple, + ); + } } diff --git a/build_system/prepare.rs b/build_system/prepare.rs index 8bb00352d3f..7e0fd182d98 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -50,8 +50,7 @@ pub(crate) fn prepare() { spawn_and_wait(build_cmd); fs::copy( Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin")), - // FIXME use get_file_name here too once testing is migrated to rust - "simple-raytracer/raytracer_cg_llvm", + Path::new("simple-raytracer").join(get_file_name("raytracer_cg_llvm", "bin")), ) .unwrap(); } diff --git a/build_system/tests.rs b/build_system/tests.rs new file mode 100644 index 00000000000..74e4b51095f --- /dev/null +++ b/build_system/tests.rs @@ -0,0 +1,504 @@ +use super::build_sysroot; +use super::config; +use super::utils::{spawn_and_wait, spawn_and_wait_with_input}; +use build_system::SysrootKind; +use std::env; +use std::ffi::OsStr; +use std::fs; +use std::path::{Path, PathBuf}; +use std::process::Command; + +type Result = std::result::Result>; + +struct TestCase { + config: &'static str, + func: &'static dyn Fn(&TestRunner), +} + +impl TestCase { + const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self { + Self { config, func } + } +} + +const NO_SYSROOT_SUITE: &[TestCase] = &[ + TestCase::new("build.mini_core", &|runner| { + runner.run_rustc(["example/mini_core.rs", "--crate-name", "mini_core", "--crate-type", "lib,dylib", "--target", &runner.target_triple]); + }), + + TestCase::new("build.example", &|runner| { + runner.run_rustc(["example/example.rs", "--crate-type", "lib", "--target", &runner.target_triple]); + }), + + TestCase::new("jit.mini_core_hello_world", &|runner| { + let mut jit_cmd = runner.rustc_command(["-Zunstable-options", "-Cllvm-args=mode=jit", "-Cprefer-dynamic", "example/mini_core_hello_world.rs", "--cfg", "jit", "--target", &runner.host_triple]); + jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd"); + spawn_and_wait(jit_cmd); + + eprintln!("[JIT-lazy] mini_core_hello_world"); + let mut jit_cmd = runner.rustc_command(["-Zunstable-options", "-Cllvm-args=mode=jit-lazy", "-Cprefer-dynamic", "example/mini_core_hello_world.rs", "--cfg", "jit", "--target", &runner.host_triple]); + jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd"); + spawn_and_wait(jit_cmd); + }), + + TestCase::new("aot.mini_core_hello_world", &|runner| { + runner.run_rustc(["example/mini_core_hello_world.rs", "--crate-name", "mini_core_hello_world", "--crate-type", "bin", "-g", "--target", &runner.target_triple]); + runner.run_out_command("mini_core_hello_world", ["abc", "bcd"]); + }), +]; + + +const BASE_SYSROOT_SUITE: &[TestCase] = &[ + TestCase::new("aot.arbitrary_self_types_pointers_and_wrappers", &|runner| { + runner.run_rustc(["example/arbitrary_self_types_pointers_and_wrappers.rs", "--crate-name", "arbitrary_self_types_pointers_and_wrappers", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_out_command("arbitrary_self_types_pointers_and_wrappers", []); + }), + + TestCase::new("aot.issue_91827_extern_types", &|runner| { + runner.run_rustc(["example/issue-91827-extern-types.rs", "--crate-name", "issue_91827_extern_types", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_out_command("issue_91827_extern_types", []); + }), + + TestCase::new("build.alloc_system", &|runner| { + runner.run_rustc(["example/alloc_system.rs", "--crate-type", "lib", "--target", &runner.target_triple]); + }), + + TestCase::new("aot.alloc_example", &|runner| { + runner.run_rustc(["example/alloc_example.rs", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_out_command("alloc_example", []); + }), + + TestCase::new("jit.std_example", &|runner| { + runner.run_rustc(["-Zunstable-options", "-Cllvm-args=mode=jit", "-Cprefer-dynamic", "example/std_example.rs", "--target", &runner.host_triple]); + + eprintln!("[JIT-lazy] std_example"); + runner.run_rustc(["-Zunstable-options", "-Cllvm-args=mode=jit-lazy", "-Cprefer-dynamic", "example/std_example.rs", "--target", &runner.host_triple]); + }), + + TestCase::new("aot.std_example", &|runner| { + runner.run_rustc(["example/std_example.rs", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_out_command("std_example", ["arg"]); + }), + + TestCase::new("aot.dst_field_align", &|runner| { + runner.run_rustc(["example/dst-field-align.rs", "--crate-name", "dst_field_align", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_out_command("dst_field_align", []); + }), + + TestCase::new("aot.subslice-patterns-const-eval", &|runner| { + runner.run_rustc(["example/subslice-patterns-const-eval.rs", "--crate-type", "bin", "-Cpanic=abort", "--target", &runner.target_triple]); + runner.run_out_command("subslice-patterns-const-eval", []); + }), + + TestCase::new("aot.track-caller-attribute", &|runner| { + runner.run_rustc(["example/track-caller-attribute.rs", "--crate-type", "bin", "-Cpanic=abort", "--target", &runner.target_triple]); + runner.run_out_command("track-caller-attribute", []); + }), + + TestCase::new("aot.float-minmax-pass", &|runner| { + runner.run_rustc(["example/float-minmax-pass.rs", "--crate-type", "bin", "-Cpanic=abort", "--target", &runner.target_triple]); + runner.run_out_command("float-minmax-pass", []); + }), + + TestCase::new("aot.mod_bench", &|runner| { + runner.run_rustc(["example/mod_bench.rs", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_out_command("mod_bench", []); + }), +]; + +const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ + TestCase::new("test.rust-random/rand", &|runner| { + runner.in_dir(["rand"], |runner| { + runner.run_cargo(["clean"]); + + if runner.host_triple == runner.target_triple { + eprintln!("[TEST] rust-random/rand"); + runner.run_cargo(["test", "--workspace"]); + } else { + eprintln!("[AOT] rust-random/rand"); + runner.run_cargo(["build", "--workspace", "--target", &runner.target_triple, "--tests"]); + } + }); + }), + + TestCase::new("bench.simple-raytracer", &|runner| { + runner.in_dir(["simple-raytracer"], |runner| { + let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()); + + if runner.host_triple == runner.target_triple { + eprintln!("[BENCH COMPILE] ebobby/simple-raytracer"); + let mut bench_compile = Command::new("hyperfine"); + bench_compile.arg("--runs"); + bench_compile.arg(&run_runs); + bench_compile.arg("--warmup"); + bench_compile.arg("1"); + bench_compile.arg("--prepare"); + bench_compile.arg(format!("{:?}", runner.cargo_command(["clean"]))); + + if cfg!(windows) { + bench_compile.arg("cmd /C \"set RUSTFLAGS= && cargo build\""); + } else { + bench_compile.arg("RUSTFLAGS='' cargo build"); + } + + bench_compile.arg(format!("{:?}", runner.cargo_command(["build"]))); + spawn_and_wait(bench_compile); + + + + eprintln!("[BENCH RUN] ebobby/simple-raytracer"); + fs::copy(PathBuf::from("./target/debug/main"), PathBuf::from("raytracer_cg_clif")).unwrap(); + + let mut bench_run = Command::new("hyperfine"); + bench_run.arg("--runs"); + bench_run.arg(&run_runs); + bench_run.arg(PathBuf::from("./raytracer_cg_llvm")); + bench_run.arg(PathBuf::from("./raytracer_cg_clif")); + spawn_and_wait(bench_run); + } else { + runner.run_cargo(["clean"]); + eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)"); + eprintln!("[COMPILE] ebobby/simple-raytracer"); + runner.run_cargo(["build", "--target", &runner.target_triple]); + eprintln!("[BENCH RUN] ebobby/simple-raytracer (skipped)"); + } + }); + }), + + TestCase::new("test.libcore", &|runner| { + runner.in_dir(["build_sysroot", "sysroot_src", "library", "core", "tests"], |runner| { + runner.run_cargo(["clean"]); + + if runner.host_triple == runner.target_triple { + runner.run_cargo(["test"]); + } else { + eprintln!("Cross-Compiling: Not running tests"); + runner.run_cargo(["build", "--target", &runner.target_triple, "--tests"]); + } + }); + }), + + TestCase::new("test.regex-shootout-regex-dna", &|runner| { + runner.in_dir(["regex"], |runner| { + runner.run_cargo(["clean"]); + + // newer aho_corasick versions throw a deprecation warning + let mut lint_rust_flags = runner.rust_flags.clone(); + lint_rust_flags.push("--cap-lints".to_string()); + lint_rust_flags.push("warn".to_string()); + + let mut build_cmd = runner.cargo_command(["build", "--example", "shootout-regex-dna", "--target", &runner.target_triple]); + build_cmd.env("RUSTFLAGS", lint_rust_flags.join(" ")); + + spawn_and_wait(build_cmd); + + if runner.host_triple == runner.target_triple { + let mut run_cmd = runner.cargo_command(["run", "--example", "shootout-regex-dna", "--target", &runner.target_triple]); + run_cmd.env("RUSTFLAGS", lint_rust_flags.join(" ")); + + + let input = fs::read_to_string(PathBuf::from("examples/regexdna-input.txt")).unwrap(); + let expected_path = PathBuf::from("examples/regexdna-output.txt"); + let expected = fs::read_to_string(&expected_path).unwrap(); + + let output = spawn_and_wait_with_input(run_cmd, input); + // Make sure `[codegen mono items] start` doesn't poison the diff + let output = output.lines() + .filter(|line| !line.contains("codegen mono items")) + .filter(|line| !line.contains("Spawned thread")) + .chain(Some("")) // This just adds the trailing newline + .collect::>() + .join("\r\n"); + + + if output != expected { + let res_path = PathBuf::from("res.txt"); + fs::write(&res_path, &output).unwrap(); + + if cfg!(windows) { + println!("Output files don't match!"); + println!("Expected Output:\n{}", expected); + println!("Actual Output:\n{}", output); + } else { + let mut diff = Command::new("diff"); + diff.arg("-u"); + diff.arg(res_path); + diff.arg(expected_path); + spawn_and_wait(diff); + } + + std::process::exit(1); + } + } + }); + }), + + TestCase::new("test.regex", &|runner| { + runner.in_dir(["regex"], |runner| { + runner.run_cargo(["clean"]); + + if runner.host_triple == runner.target_triple { + runner.run_cargo(["test", "--tests", "--", "--exclude-should-panic", "--test-threads", "1", "-Zunstable-options", "-q"]); + } else { + eprintln!("Cross-Compiling: Not running tests"); + runner.run_cargo(["build", "--tests", "--target", &runner.target_triple]); + } + }); + }), + + TestCase::new("test.portable-simd", &|runner| { + runner.in_dir(["portable-simd"], |runner| { + runner.run_cargo(["clean"]); + runner.run_cargo(["build", "--all-targets", "--target", &runner.target_triple]); + + if runner.host_triple == runner.target_triple { + runner.run_cargo(["test", "-q"]); + } + }); + }), +]; + + + +pub(crate) fn run_tests( + channel: &str, + sysroot_kind: SysrootKind, + target_dir: &Path, + cg_clif_build_dir: &Path, + host_triple: &str, + target_triple: &str, +) -> Result<()> { + let runner = TestRunner::new(host_triple.to_string(), target_triple.to_string()); + + if config::get_bool("testsuite.no_sysroot") { + build_sysroot::build_sysroot( + channel, + SysrootKind::None, + &target_dir, + cg_clif_build_dir, + &host_triple, + &target_triple, + ); + + let _ = remove_out_dir(); + runner.run_testsuite(NO_SYSROOT_SUITE); + } else { + eprintln!("[SKIP] no_sysroot tests"); + } + + let run_base_sysroot = config::get_bool("testsuite.base_sysroot"); + let run_extended_sysroot = config::get_bool("testsuite.extended_sysroot"); + + if run_base_sysroot || run_extended_sysroot { + build_sysroot::build_sysroot( + channel, + sysroot_kind, + &target_dir, + cg_clif_build_dir, + &host_triple, + &target_triple, + ); + } + + if run_base_sysroot { + runner.run_testsuite(BASE_SYSROOT_SUITE); + } else { + eprintln!("[SKIP] base_sysroot tests"); + } + + if run_extended_sysroot { + runner.run_testsuite(EXTENDED_SYSROOT_SUITE); + } else { + eprintln!("[SKIP] extended_sysroot tests"); + } + + Ok(()) +} + + +fn remove_out_dir() -> Result<()> { + let out_dir = Path::new("target").join("out"); + Ok(fs::remove_dir_all(out_dir)?) +} + +struct TestRunner { + root_dir: PathBuf, + out_dir: PathBuf, + jit_supported: bool, + rust_flags: Vec, + run_wrapper: Vec, + host_triple: String, + target_triple: String, +} + +impl TestRunner { + pub fn new(host_triple: String, target_triple: String) -> Self { + let root_dir = env::current_dir().unwrap(); + + let mut out_dir = root_dir.clone(); + out_dir.push("target"); + out_dir.push("out"); + + let is_native = host_triple == target_triple; + let jit_supported = target_triple.contains("x86_64") && is_native; + + let env_rust_flags = env::var("RUSTFLAGS").ok(); + let env_run_wrapper = env::var("RUN_WRAPPER").ok(); + + let mut rust_flags: Vec<&str> = env_rust_flags.iter().map(|s| s.as_str()).collect(); + let mut run_wrapper: Vec<&str> = env_run_wrapper.iter().map(|s| s.as_str()).collect(); + + if !is_native { + match target_triple.as_str() { + "aarch64-unknown-linux-gnu" => { + // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu. + rust_flags.insert(0, "-Clinker=aarch64-linux-gnu-gcc"); + run_wrapper.extend(["qemu-aarch64", "-L", "/usr/aarch64-linux-gnu"]); + }, + "x86_64-pc-windows-gnu" => { + // We are cross-compiling for Windows. Run tests in wine. + run_wrapper.push("wine".into()); + } + _ => { + println!("Unknown non-native platform"); + } + } + } + + // FIXME fix `#[linkage = "extern_weak"]` without this + if host_triple.contains("darwin") { + rust_flags.push("-Clink-arg=-undefined"); + rust_flags.push("-Clink-arg=dynamic_lookup"); + } + + Self { + root_dir, + out_dir, + jit_supported, + rust_flags: rust_flags.iter().map(|s| s.to_string()).collect(), + run_wrapper: run_wrapper.iter().map(|s| s.to_string()).collect(), + host_triple, + target_triple, + } + } + + pub fn run_testsuite(&self, tests: &[TestCase]) { + for &TestCase { config, func } in tests { + let is_jit_test = config.contains("jit"); + let (tag, testname) = config.split_once('.').unwrap(); + let tag = tag.to_uppercase(); + + if !config::get_bool(config) || (is_jit_test && !self.jit_supported) { + eprintln!("[{tag}] {testname} (skipped)"); + continue; + } else { + eprintln!("[{tag}] {testname}"); + } + + func(self); + } + } + + fn in_dir<'a, I, F>(&self, dir: I, callback: F) + where + I: IntoIterator, + F: FnOnce(&TestRunner), + { + let current = env::current_dir().unwrap(); + let mut new = current.clone(); + for d in dir { + new.push(d); + } + + env::set_current_dir(new).unwrap(); + callback(self); + env::set_current_dir(current).unwrap(); + } + + fn rustc_command(&self, args: I) -> Command + where + I: IntoIterator, + S: AsRef, + { + let mut rustc_clif = self.root_dir.clone(); + rustc_clif.push("build"); + rustc_clif.push("rustc-clif"); + if cfg!(windows) { + rustc_clif.set_extension("exe"); + } + + let mut cmd = Command::new(rustc_clif); + cmd.args(self.rust_flags.iter()); + cmd.arg("-L"); + cmd.arg(format!("crate={}", self.out_dir.display())); + cmd.arg("--out-dir"); + cmd.arg(format!("{}", self.out_dir.display())); + cmd.arg("-Cdebuginfo=2"); + cmd.args(args); + cmd.env("RUSTFLAGS", self.rust_flags.join(" ")); + cmd + } + + fn run_rustc(&self, args: I) + where + I: IntoIterator, + S: AsRef, + { + spawn_and_wait(self.rustc_command(args)); + } + + fn run_out_command<'a, I>(&self, name: &str, args: I) + where + I: IntoIterator, + { + let mut full_cmd = vec![]; + + // Prepend the RUN_WRAPPER's + for rw in self.run_wrapper.iter() { + full_cmd.push(rw.to_string()); + } + + full_cmd.push({ + let mut out_path = self.out_dir.clone(); + out_path.push(name); + out_path.to_str().unwrap().to_string() + }); + + for arg in args.into_iter() { + full_cmd.push(arg.to_string()); + } + + let mut cmd_iter = full_cmd.into_iter(); + let first = cmd_iter.next().unwrap(); + + let mut cmd = Command::new(first); + cmd.args(cmd_iter); + + spawn_and_wait(cmd); + } + + fn cargo_command(&self, args: I) -> Command + where + I: IntoIterator, + S: AsRef, + { + let mut cargo_clif = self.root_dir.clone(); + cargo_clif.push("build"); + cargo_clif.push("cargo-clif"); + if cfg!(windows) { + cargo_clif.set_extension("exe"); + } + + let mut cmd = Command::new(cargo_clif); + cmd.args(args); + cmd.env("RUSTFLAGS", self.rust_flags.join(" ")); + cmd + } + + fn run_cargo<'a, I>(&self, args: I) + where + I: IntoIterator, + { + spawn_and_wait(self.cargo_command(args)); + } +} diff --git a/build_system/utils.rs b/build_system/utils.rs index 12b5d70fad8..2d2778d2fc0 100644 --- a/build_system/utils.rs +++ b/build_system/utils.rs @@ -1,6 +1,7 @@ use std::fs; use std::path::Path; -use std::process::{self, Command}; +use std::process::{self, Command, Stdio}; +use std::io::Write; #[track_caller] pub(crate) fn try_hard_link(src: impl AsRef, dst: impl AsRef) { @@ -18,6 +19,27 @@ pub(crate) fn spawn_and_wait(mut cmd: Command) { } } +#[track_caller] +pub(crate) fn spawn_and_wait_with_input(mut cmd: Command, input: String) -> String { + let mut child = cmd + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .expect("Failed to spawn child process"); + + let mut stdin = child.stdin.take().expect("Failed to open stdin"); + std::thread::spawn(move || { + stdin.write_all(input.as_bytes()).expect("Failed to write to stdin"); + }); + + let output = child.wait_with_output().expect("Failed to read stdout"); + if !output.status.success() { + process::exit(1); + } + + String::from_utf8(output.stdout).unwrap() +} + pub(crate) fn copy_dir_recursively(from: &Path, to: &Path) { for entry in fs::read_dir(from).unwrap() { let entry = entry.unwrap(); diff --git a/config.txt b/config.txt index b14db27d620..5e4d230776d 100644 --- a/config.txt +++ b/config.txt @@ -15,3 +15,36 @@ # This option can be changed while the build system is already running for as long as sysroot # building hasn't started yet. #keep_sysroot + + +# Testsuite +# +# Each test suite item has a corresponding key here. The default is to run all tests. +# Comment any of these lines to skip individual tests. + +testsuite.no_sysroot +build.mini_core +build.example +jit.mini_core_hello_world +aot.mini_core_hello_world + +testsuite.base_sysroot +aot.arbitrary_self_types_pointers_and_wrappers +aot.issue_91827_extern_types +build.alloc_system +aot.alloc_example +jit.std_example +aot.std_example +aot.dst_field_align +aot.subslice-patterns-const-eval +aot.track-caller-attribute +aot.float-minmax-pass +aot.mod_bench + +testsuite.extended_sysroot +test.rust-random/rand +bench.simple-raytracer +test.libcore +test.regex-shootout-regex-dna +test.regex +test.portable-simd diff --git a/scripts/tests.sh b/scripts/tests.sh deleted file mode 100755 index 9b5ffa40960..00000000000 --- a/scripts/tests.sh +++ /dev/null @@ -1,203 +0,0 @@ -#!/usr/bin/env bash - -set -e - -export CG_CLIF_DISPLAY_CG_TIME=1 -export CG_CLIF_DISABLE_INCR_CACHE=1 - -export HOST_TRIPLE=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ") -export TARGET_TRIPLE=${TARGET_TRIPLE:-$HOST_TRIPLE} - -export RUN_WRAPPER='' - -case "$TARGET_TRIPLE" in - x86_64*) - export JIT_SUPPORTED=1 - ;; - *) - export JIT_SUPPORTED=0 - ;; -esac - -if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then - export JIT_SUPPORTED=0 - if [[ "$TARGET_TRIPLE" == "aarch64-unknown-linux-gnu" ]]; then - # We are cross-compiling for aarch64. Use the correct linker and run tests in qemu. - export RUSTFLAGS='-Clinker=aarch64-linux-gnu-gcc '$RUSTFLAGS - export RUN_WRAPPER='qemu-aarch64 -L /usr/aarch64-linux-gnu' - elif [[ "$TARGET_TRIPLE" == "x86_64-pc-windows-gnu" ]]; then - # We are cross-compiling for Windows. Run tests in wine. - export RUN_WRAPPER='wine' - else - echo "Unknown non-native platform" - fi -fi - -# FIXME fix `#[linkage = "extern_weak"]` without this -if [[ "$(uname)" == 'Darwin' ]]; then - export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup" -fi - -MY_RUSTC="$(pwd)/build/rustc-clif $RUSTFLAGS -L crate=target/out --out-dir target/out -Cdebuginfo=2" - -function no_sysroot_tests() { - echo "[BUILD] mini_core" - $MY_RUSTC example/mini_core.rs --crate-name mini_core --crate-type lib,dylib --target "$TARGET_TRIPLE" - - echo "[BUILD] example" - $MY_RUSTC example/example.rs --crate-type lib --target "$TARGET_TRIPLE" - - if [[ "$JIT_SUPPORTED" = "1" ]]; then - echo "[JIT] mini_core_hello_world" - CG_CLIF_JIT_ARGS="abc bcd" $MY_RUSTC -Zunstable-options -Cllvm-args=mode=jit -Cprefer-dynamic example/mini_core_hello_world.rs --cfg jit --target "$HOST_TRIPLE" - - echo "[JIT-lazy] mini_core_hello_world" - CG_CLIF_JIT_ARGS="abc bcd" $MY_RUSTC -Zunstable-options -Cllvm-args=mode=jit-lazy -Cprefer-dynamic example/mini_core_hello_world.rs --cfg jit --target "$HOST_TRIPLE" - else - echo "[JIT] mini_core_hello_world (skipped)" - fi - - echo "[AOT] mini_core_hello_world" - $MY_RUSTC example/mini_core_hello_world.rs --crate-name mini_core_hello_world --crate-type bin -g --target "$TARGET_TRIPLE" - $RUN_WRAPPER ./target/out/mini_core_hello_world abc bcd - # (echo "break set -n main"; echo "run"; sleep 1; echo "si -c 10"; sleep 1; echo "frame variable") | lldb -- ./target/out/mini_core_hello_world abc bcd -} - -function base_sysroot_tests() { - echo "[AOT] arbitrary_self_types_pointers_and_wrappers" - $MY_RUSTC example/arbitrary_self_types_pointers_and_wrappers.rs --crate-name arbitrary_self_types_pointers_and_wrappers --crate-type bin --target "$TARGET_TRIPLE" - $RUN_WRAPPER ./target/out/arbitrary_self_types_pointers_and_wrappers - - echo "[AOT] issue_91827_extern_types" - $MY_RUSTC example/issue-91827-extern-types.rs --crate-name issue_91827_extern_types --crate-type bin --target "$TARGET_TRIPLE" - $RUN_WRAPPER ./target/out/issue_91827_extern_types - - echo "[BUILD] alloc_system" - $MY_RUSTC example/alloc_system.rs --crate-type lib --target "$TARGET_TRIPLE" - - echo "[AOT] alloc_example" - $MY_RUSTC example/alloc_example.rs --crate-type bin --target "$TARGET_TRIPLE" - $RUN_WRAPPER ./target/out/alloc_example - - if [[ "$JIT_SUPPORTED" = "1" ]]; then - echo "[JIT] std_example" - $MY_RUSTC -Zunstable-options -Cllvm-args=mode=jit -Cprefer-dynamic example/std_example.rs --target "$HOST_TRIPLE" - - echo "[JIT-lazy] std_example" - $MY_RUSTC -Zunstable-options -Cllvm-args=mode=jit-lazy -Cprefer-dynamic example/std_example.rs --target "$HOST_TRIPLE" - else - echo "[JIT] std_example (skipped)" - fi - - echo "[AOT] std_example" - $MY_RUSTC example/std_example.rs --crate-type bin --target "$TARGET_TRIPLE" - $RUN_WRAPPER ./target/out/std_example arg - - echo "[AOT] dst_field_align" - $MY_RUSTC example/dst-field-align.rs --crate-name dst_field_align --crate-type bin --target "$TARGET_TRIPLE" - $RUN_WRAPPER ./target/out/dst_field_align - - echo "[AOT] subslice-patterns-const-eval" - $MY_RUSTC example/subslice-patterns-const-eval.rs --crate-type bin -Cpanic=abort --target "$TARGET_TRIPLE" - $RUN_WRAPPER ./target/out/subslice-patterns-const-eval - - echo "[AOT] track-caller-attribute" - $MY_RUSTC example/track-caller-attribute.rs --crate-type bin -Cpanic=abort --target "$TARGET_TRIPLE" - $RUN_WRAPPER ./target/out/track-caller-attribute - - echo "[AOT] float-minmax-pass" - $MY_RUSTC example/float-minmax-pass.rs --crate-type bin -Cpanic=abort --target "$TARGET_TRIPLE" - $RUN_WRAPPER ./target/out/float-minmax-pass - - echo "[AOT] mod_bench" - $MY_RUSTC example/mod_bench.rs --crate-type bin --target "$TARGET_TRIPLE" - $RUN_WRAPPER ./target/out/mod_bench -} - -function extended_sysroot_tests() { - pushd rand - ../build/cargo-clif clean - if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then - echo "[TEST] rust-random/rand" - ../build/cargo-clif test --workspace - else - echo "[AOT] rust-random/rand" - ../build/cargo-clif build --workspace --target $TARGET_TRIPLE --tests - fi - popd - - pushd simple-raytracer - if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then - echo "[BENCH COMPILE] ebobby/simple-raytracer" - hyperfine --runs "${RUN_RUNS:-10}" --warmup 1 --prepare "../build/cargo-clif clean" \ - "RUSTFLAGS='' cargo build" \ - "../build/cargo-clif build" - - echo "[BENCH RUN] ebobby/simple-raytracer" - cp ./target/debug/main ./raytracer_cg_clif - hyperfine --runs "${RUN_RUNS:-10}" ./raytracer_cg_llvm ./raytracer_cg_clif - else - ../build/cargo-clif clean - echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)" - echo "[COMPILE] ebobby/simple-raytracer" - ../build/cargo-clif build --target $TARGET_TRIPLE - echo "[BENCH RUN] ebobby/simple-raytracer (skipped)" - fi - popd - - pushd build_sysroot/sysroot_src/library/core/tests - echo "[TEST] libcore" - ../../../../../build/cargo-clif clean - if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then - ../../../../../build/cargo-clif test - else - ../../../../../build/cargo-clif build --target $TARGET_TRIPLE --tests - fi - popd - - pushd regex - echo "[TEST] rust-lang/regex example shootout-regex-dna" - ../build/cargo-clif clean - export RUSTFLAGS="$RUSTFLAGS --cap-lints warn" # newer aho_corasick versions throw a deprecation warning - # Make sure `[codegen mono items] start` doesn't poison the diff - ../build/cargo-clif build --example shootout-regex-dna --target $TARGET_TRIPLE - if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then - cat examples/regexdna-input.txt \ - | ../build/cargo-clif run --example shootout-regex-dna --target $TARGET_TRIPLE \ - | grep -v "Spawned thread" > res.txt - diff -u res.txt examples/regexdna-output.txt - fi - - if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then - echo "[TEST] rust-lang/regex tests" - ../build/cargo-clif test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q - else - echo "[AOT] rust-lang/regex tests" - ../build/cargo-clif build --tests --target $TARGET_TRIPLE - fi - popd - - pushd portable-simd - echo "[TEST] rust-lang/portable-simd" - ../build/cargo-clif clean - ../build/cargo-clif build --all-targets --target $TARGET_TRIPLE - if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then - ../build/cargo-clif test -q - fi - popd -} - -case "$1" in - "no_sysroot") - no_sysroot_tests - ;; - "base_sysroot") - base_sysroot_tests - ;; - "extended_sysroot") - extended_sysroot_tests - ;; - *) - echo "unknown test suite" - ;; -esac diff --git a/test.sh b/test.sh deleted file mode 100755 index a10924628bb..00000000000 --- a/test.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash -set -e - -./y.rs build --sysroot none "$@" - -rm -r target/out || true - -scripts/tests.sh no_sysroot - -./y.rs build "$@" - -scripts/tests.sh base_sysroot -scripts/tests.sh extended_sysroot -- cgit 1.4.1-3-g733a5 From c115933fb7be123b6dacc6e95cb87ae44e6d5296 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 12:48:46 +0100 Subject: Run tests on windows CI --- .github/workflows/main.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a36c570ddc8..1a947d3551c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -159,19 +159,21 @@ jobs: ./y.exe prepare - name: Build - #name: Test + run: ./y.exe build + + - name: Test run: | # Enable backtraces for easier debugging - #export RUST_BACKTRACE=1 + export RUST_BACKTRACE=1 # Reduce amount of benchmark runs as they are slow - #export COMPILE_RUNS=2 - #export RUN_RUNS=2 + export COMPILE_RUNS=2 + export RUN_RUNS=2 # Enable extra checks - #export CG_CLIF_ENABLE_VERIFIER=1 + export CG_CLIF_ENABLE_VERIFIER=1 - ./y.exe build + ./y.exe test - name: Package prebuilt cg_clif # don't use compression as xzip isn't supported by tar on windows and bzip2 hangs -- cgit 1.4.1-3-g733a5 From d0599350a742dfee6f1ff9e60ac91fc2b673a972 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 12:50:05 +0100 Subject: Misc cleanups to the test runner --- build_system/build_backend.rs | 5 +++- build_system/mod.rs | 45 +++++++++++++++++---------------- build_system/tests.rs | 59 +++++++++++++++++-------------------------- 3 files changed, 50 insertions(+), 59 deletions(-) diff --git a/build_system/build_backend.rs b/build_system/build_backend.rs index 04f8be6f820..ddc099b5388 100644 --- a/build_system/build_backend.rs +++ b/build_system/build_backend.rs @@ -1,11 +1,12 @@ use std::env; +use std::path::{Path, PathBuf}; use std::process::Command; pub(crate) fn build_backend( channel: &str, host_triple: &str, use_unstable_features: bool, -) { +) -> PathBuf { let mut cmd = Command::new("cargo"); cmd.arg("build").arg("--target").arg(host_triple); @@ -37,4 +38,6 @@ pub(crate) fn build_backend( eprintln!("[BUILD] rustc_codegen_cranelift"); super::utils::spawn_and_wait(cmd); + + Path::new("target").join(&host_triple).join(&channel) } diff --git a/build_system/mod.rs b/build_system/mod.rs index d1f8ad3e817..af75cef04e0 100644 --- a/build_system/mod.rs +++ b/build_system/mod.rs @@ -1,5 +1,5 @@ use std::env; -use std::path::{PathBuf, Path}; +use std::path::PathBuf; use std::process; mod build_backend; @@ -122,27 +122,28 @@ pub fn main() { process::exit(1); } - let cg_clif_build_dir = Path::new("target").join(&host_triple).join(&channel); + let cg_clif_build_dir = build_backend::build_backend(channel, &host_triple, use_unstable_features); - if command == Command::Test { - // TODO: Should we also build_backend here? - tests::run_tests( - channel, - sysroot_kind, - &target_dir, - &cg_clif_build_dir, - &host_triple, - &target_triple, - ).expect("Failed to run tests"); - } else { - build_backend::build_backend(channel, &host_triple, use_unstable_features); - build_sysroot::build_sysroot( - channel, - sysroot_kind, - &target_dir, - &cg_clif_build_dir, - &host_triple, - &target_triple, - ); + match command { + Command::Test => { + tests::run_tests( + channel, + sysroot_kind, + &target_dir, + &cg_clif_build_dir, + &host_triple, + &target_triple, + ); + }, + Command::Build => { + build_sysroot::build_sysroot( + channel, + sysroot_kind, + &target_dir, + &cg_clif_build_dir, + &host_triple, + &target_triple, + ); + } } } diff --git a/build_system/tests.rs b/build_system/tests.rs index 74e4b51095f..f2166b20fcb 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -8,8 +8,6 @@ use std::fs; use std::path::{Path, PathBuf}; use std::process::Command; -type Result = std::result::Result>; - struct TestCase { config: &'static str, func: &'static dyn Fn(&TestRunner), @@ -183,18 +181,16 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ runner.run_cargo(["clean"]); // newer aho_corasick versions throw a deprecation warning - let mut lint_rust_flags = runner.rust_flags.clone(); - lint_rust_flags.push("--cap-lints".to_string()); - lint_rust_flags.push("warn".to_string()); + let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags); let mut build_cmd = runner.cargo_command(["build", "--example", "shootout-regex-dna", "--target", &runner.target_triple]); - build_cmd.env("RUSTFLAGS", lint_rust_flags.join(" ")); + build_cmd.env("RUSTFLAGS", lint_rust_flags.clone()); spawn_and_wait(build_cmd); if runner.host_triple == runner.target_triple { let mut run_cmd = runner.cargo_command(["run", "--example", "shootout-regex-dna", "--target", &runner.target_triple]); - run_cmd.env("RUSTFLAGS", lint_rust_flags.join(" ")); + run_cmd.env("RUSTFLAGS", lint_rust_flags); let input = fs::read_to_string(PathBuf::from("examples/regexdna-input.txt")).unwrap(); @@ -205,7 +201,6 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ // Make sure `[codegen mono items] start` doesn't poison the diff let output = output.lines() .filter(|line| !line.contains("codegen mono items")) - .filter(|line| !line.contains("Spawned thread")) .chain(Some("")) // This just adds the trailing newline .collect::>() .join("\r\n"); @@ -267,7 +262,7 @@ pub(crate) fn run_tests( cg_clif_build_dir: &Path, host_triple: &str, target_triple: &str, -) -> Result<()> { +) { let runner = TestRunner::new(host_triple.to_string(), target_triple.to_string()); if config::get_bool("testsuite.no_sysroot") { @@ -280,7 +275,7 @@ pub(crate) fn run_tests( &target_triple, ); - let _ = remove_out_dir(); + let _ = fs::remove_dir_all(Path::new("target").join("out")); runner.run_testsuite(NO_SYSROOT_SUITE); } else { eprintln!("[SKIP] no_sysroot tests"); @@ -311,22 +306,16 @@ pub(crate) fn run_tests( } else { eprintln!("[SKIP] extended_sysroot tests"); } - - Ok(()) } -fn remove_out_dir() -> Result<()> { - let out_dir = Path::new("target").join("out"); - Ok(fs::remove_dir_all(out_dir)?) -} struct TestRunner { root_dir: PathBuf, out_dir: PathBuf, jit_supported: bool, - rust_flags: Vec, - run_wrapper: Vec, + rust_flags: String, + run_wrapper: String, host_triple: String, target_triple: String, } @@ -342,22 +331,19 @@ impl TestRunner { let is_native = host_triple == target_triple; let jit_supported = target_triple.contains("x86_64") && is_native; - let env_rust_flags = env::var("RUSTFLAGS").ok(); - let env_run_wrapper = env::var("RUN_WRAPPER").ok(); - - let mut rust_flags: Vec<&str> = env_rust_flags.iter().map(|s| s.as_str()).collect(); - let mut run_wrapper: Vec<&str> = env_run_wrapper.iter().map(|s| s.as_str()).collect(); + let mut rust_flags = env::var("RUSTFLAGS").ok().unwrap_or("".to_string()); + let mut run_wrapper = String::new(); if !is_native { match target_triple.as_str() { "aarch64-unknown-linux-gnu" => { // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu. - rust_flags.insert(0, "-Clinker=aarch64-linux-gnu-gcc"); - run_wrapper.extend(["qemu-aarch64", "-L", "/usr/aarch64-linux-gnu"]); + rust_flags = format!("-Clinker=aarch64-linux-gnu-gcc {}", rust_flags); + run_wrapper = "qemu-aarch64 -L /usr/aarch64-linux-gnu".to_string(); }, "x86_64-pc-windows-gnu" => { // We are cross-compiling for Windows. Run tests in wine. - run_wrapper.push("wine".into()); + run_wrapper = "wine".to_string(); } _ => { println!("Unknown non-native platform"); @@ -367,16 +353,15 @@ impl TestRunner { // FIXME fix `#[linkage = "extern_weak"]` without this if host_triple.contains("darwin") { - rust_flags.push("-Clink-arg=-undefined"); - rust_flags.push("-Clink-arg=dynamic_lookup"); + rust_flags = format!("{} -Clink-arg=-undefined -Clink-arg=dynamic_lookup", rust_flags); } Self { root_dir, out_dir, jit_supported, - rust_flags: rust_flags.iter().map(|s| s.to_string()).collect(), - run_wrapper: run_wrapper.iter().map(|s| s.to_string()).collect(), + rust_flags, + run_wrapper, host_triple, target_triple, } @@ -384,9 +369,9 @@ impl TestRunner { pub fn run_testsuite(&self, tests: &[TestCase]) { for &TestCase { config, func } in tests { - let is_jit_test = config.contains("jit"); let (tag, testname) = config.split_once('.').unwrap(); let tag = tag.to_uppercase(); + let is_jit_test = tag == "JIT"; if !config::get_bool(config) || (is_jit_test && !self.jit_supported) { eprintln!("[{tag}] {testname} (skipped)"); @@ -428,14 +413,16 @@ impl TestRunner { } let mut cmd = Command::new(rustc_clif); - cmd.args(self.rust_flags.iter()); + if !self.rust_flags.is_empty() { + cmd.arg(&self.rust_flags); + } cmd.arg("-L"); cmd.arg(format!("crate={}", self.out_dir.display())); cmd.arg("--out-dir"); cmd.arg(format!("{}", self.out_dir.display())); cmd.arg("-Cdebuginfo=2"); cmd.args(args); - cmd.env("RUSTFLAGS", self.rust_flags.join(" ")); + cmd.env("RUSTFLAGS", &self.rust_flags); cmd } @@ -454,8 +441,8 @@ impl TestRunner { let mut full_cmd = vec![]; // Prepend the RUN_WRAPPER's - for rw in self.run_wrapper.iter() { - full_cmd.push(rw.to_string()); + if !self.run_wrapper.is_empty() { + full_cmd.push(self.run_wrapper.clone()); } full_cmd.push({ @@ -491,7 +478,7 @@ impl TestRunner { let mut cmd = Command::new(cargo_clif); cmd.args(args); - cmd.env("RUSTFLAGS", self.rust_flags.join(" ")); + cmd.env("RUSTFLAGS", &self.rust_flags); cmd } -- cgit 1.4.1-3-g733a5 From 437b441ff5e9fd5e9d837db1cb03529344b41db1 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 13:06:37 +0100 Subject: Use get_file_name everywhere for better cross compilation support --- build_system/build_sysroot.rs | 11 ++++---- build_system/mod.rs | 61 ++++++++++++++++++++++--------------------- build_system/prepare.rs | 6 ++--- build_system/rustc_info.rs | 4 ++- 4 files changed, 42 insertions(+), 40 deletions(-) diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index dddd5a673c5..14e82a77f86 100644 --- a/build_system/build_sysroot.rs +++ b/build_system/build_sysroot.rs @@ -23,7 +23,7 @@ pub(crate) fn build_sysroot( fs::create_dir_all(target_dir.join("lib")).unwrap(); // Copy the backend - let cg_clif_dylib = get_file_name("rustc_codegen_cranelift", "dylib"); + let cg_clif_dylib = get_file_name("rustc_codegen_cranelift", "dylib", target_triple); let cg_clif_dylib_path = target_dir .join(if cfg!(windows) { // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the @@ -37,11 +37,10 @@ pub(crate) fn build_sysroot( // Build and copy rustc and cargo wrappers for wrapper in ["rustc-clif", "cargo-clif"] { - let wrapper_name = if cfg!(windows) { - format!("{wrapper}.exe") - } else { - wrapper.to_string() - }; + let crate_name = wrapper.replace('-', "_"); + let wrapper_name = get_file_name(&crate_name, "bin", target_triple); + let wrapper_name = wrapper_name.replace('_', "-"); + let mut build_cargo_wrapper_cmd = Command::new("rustc"); build_cargo_wrapper_cmd diff --git a/build_system/mod.rs b/build_system/mod.rs index af75cef04e0..0124d47de75 100644 --- a/build_system/mod.rs +++ b/build_system/mod.rs @@ -48,13 +48,42 @@ pub fn main() { // The target dir is expected in the default location. Guard against the user changing it. env::set_var("CARGO_TARGET_DIR", "target"); + + let host_triple = if let Ok(host_triple) = std::env::var("HOST_TRIPLE") { + host_triple + } else if let Some(host_triple) = config::get_value("host") { + host_triple + } else { + rustc_info::get_host_triple() + }; + let target_triple = if let Ok(target_triple) = std::env::var("TARGET_TRIPLE") { + if target_triple != "" { + target_triple + } else { + host_triple.clone() // Empty target triple can happen on GHA + } + } else if let Some(target_triple) = config::get_value("target") { + target_triple + } else { + host_triple.clone() + }; + + if target_triple.ends_with("-msvc") { + eprintln!("The MSVC toolchain is not yet supported by rustc_codegen_cranelift."); + eprintln!("Switch to the MinGW toolchain for Windows support."); + eprintln!("Hint: You can use `rustup set default-host x86_64-pc-windows-gnu` to"); + eprintln!("set the global default target to MinGW"); + // process::exit(1); + } + + let mut args = env::args().skip(1); let command = match args.next().as_deref() { Some("prepare") => { if args.next().is_some() { - arg_error!("./x.rs prepare doesn't expect arguments"); + arg_error!("./y.rs prepare doesn't expect arguments"); } - prepare::prepare(); + prepare::prepare(&target_triple); process::exit(0); } Some("build") => Command::Build, @@ -95,35 +124,7 @@ pub fn main() { } target_dir = std::env::current_dir().unwrap().join(target_dir); - let host_triple = if let Ok(host_triple) = std::env::var("HOST_TRIPLE") { - host_triple - } else if let Some(host_triple) = config::get_value("host") { - host_triple - } else { - rustc_info::get_host_triple() - }; - let target_triple = if let Ok(target_triple) = std::env::var("TARGET_TRIPLE") { - if target_triple != "" { - target_triple - } else { - host_triple.clone() // Empty target triple can happen on GHA - } - } else if let Some(target_triple) = config::get_value("target") { - target_triple - } else { - host_triple.clone() - }; - - if target_triple.ends_with("-msvc") { - eprintln!("The MSVC toolchain is not yet supported by rustc_codegen_cranelift."); - eprintln!("Switch to the MinGW toolchain for Windows support."); - eprintln!("Hint: You can use `rustup set default-host x86_64-pc-windows-gnu` to"); - eprintln!("set the global default target to MinGW"); - process::exit(1); - } - let cg_clif_build_dir = build_backend::build_backend(channel, &host_triple, use_unstable_features); - match command { Command::Test => { tests::run_tests( diff --git a/build_system/prepare.rs b/build_system/prepare.rs index 7e0fd182d98..4580c4b6549 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -8,7 +8,7 @@ use std::process::Command; use super::rustc_info::{get_file_name, get_rustc_path, get_rustc_version}; use super::utils::{copy_dir_recursively, spawn_and_wait}; -pub(crate) fn prepare() { +pub(crate) fn prepare(target_triple: &str) { prepare_sysroot(); eprintln!("[INSTALL] hyperfine"); @@ -49,8 +49,8 @@ pub(crate) fn prepare() { build_cmd.arg("build").env_remove("CARGO_TARGET_DIR").current_dir("simple-raytracer"); spawn_and_wait(build_cmd); fs::copy( - Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin")), - Path::new("simple-raytracer").join(get_file_name("raytracer_cg_llvm", "bin")), + Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin", target_triple)), + Path::new("simple-raytracer").join(get_file_name("raytracer_cg_llvm", "bin", target_triple)), ) .unwrap(); } diff --git a/build_system/rustc_info.rs b/build_system/rustc_info.rs index 9206bb02bd3..f9689eb2a8c 100644 --- a/build_system/rustc_info.rs +++ b/build_system/rustc_info.rs @@ -43,7 +43,7 @@ pub(crate) fn get_default_sysroot() -> PathBuf { Path::new(String::from_utf8(default_sysroot).unwrap().trim()).to_owned() } -pub(crate) fn get_file_name(crate_name: &str, crate_type: &str) -> String { +pub(crate) fn get_file_name(crate_name: &str, crate_type: &str, target: &str) -> String { let file_name = Command::new("rustc") .stderr(Stdio::inherit()) .args(&[ @@ -51,6 +51,8 @@ pub(crate) fn get_file_name(crate_name: &str, crate_type: &str) -> String { crate_name, "--crate-type", crate_type, + "--target", + target, "--print", "file-names", "-", -- cgit 1.4.1-3-g733a5 From ae4fe1d57dd2a00523705f0425a82a759c9bfa3c Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 14:07:02 +0100 Subject: Use get_file_name in tests --- build_system/build_sysroot.rs | 7 ++----- build_system/rustc_info.rs | 9 +++++++++ build_system/tests.rs | 11 +++-------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index 14e82a77f86..cd3216cd624 100644 --- a/build_system/build_sysroot.rs +++ b/build_system/build_sysroot.rs @@ -2,7 +2,7 @@ use std::fs; use std::path::{Path, PathBuf}; use std::process::{self, Command}; -use super::rustc_info::{get_file_name, get_rustc_version}; +use super::rustc_info::{get_file_name, get_wrapper_file_name, get_rustc_version}; use super::utils::{spawn_and_wait, try_hard_link}; use super::SysrootKind; @@ -37,10 +37,7 @@ pub(crate) fn build_sysroot( // Build and copy rustc and cargo wrappers for wrapper in ["rustc-clif", "cargo-clif"] { - let crate_name = wrapper.replace('-', "_"); - let wrapper_name = get_file_name(&crate_name, "bin", target_triple); - let wrapper_name = wrapper_name.replace('_', "-"); - + let wrapper_name = get_wrapper_file_name(wrapper, "bin", target_triple); let mut build_cargo_wrapper_cmd = Command::new("rustc"); build_cargo_wrapper_cmd diff --git a/build_system/rustc_info.rs b/build_system/rustc_info.rs index f9689eb2a8c..63e1d16ead6 100644 --- a/build_system/rustc_info.rs +++ b/build_system/rustc_info.rs @@ -65,3 +65,12 @@ pub(crate) fn get_file_name(crate_name: &str, crate_type: &str, target: &str) -> assert!(file_name.contains(crate_name)); file_name } + +/// Similar to `get_file_name`, but converts any dashes (`-`) in the `crate_name` to +/// underscores (`_`). This is specially made for the the rustc and cargo wrappers +/// which have a dash in the name, and that is not allowed in a crate name. +pub(crate) fn get_wrapper_file_name(crate_name: &str, crate_type: &str, target: &str) -> String { + let crate_name = crate_name.replace('-', "_"); + let wrapper_name = get_file_name(&crate_name, crate_type, target); + wrapper_name.replace('_', "-") +} diff --git a/build_system/tests.rs b/build_system/tests.rs index f2166b20fcb..20d600effd3 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -1,5 +1,6 @@ use super::build_sysroot; use super::config; +use super::rustc_info::get_wrapper_file_name; use super::utils::{spawn_and_wait, spawn_and_wait_with_input}; use build_system::SysrootKind; use std::env; @@ -407,10 +408,7 @@ impl TestRunner { { let mut rustc_clif = self.root_dir.clone(); rustc_clif.push("build"); - rustc_clif.push("rustc-clif"); - if cfg!(windows) { - rustc_clif.set_extension("exe"); - } + rustc_clif.push(get_wrapper_file_name("rustc-clif", "bin", &self.target_triple)); let mut cmd = Command::new(rustc_clif); if !self.rust_flags.is_empty() { @@ -471,10 +469,7 @@ impl TestRunner { { let mut cargo_clif = self.root_dir.clone(); cargo_clif.push("build"); - cargo_clif.push("cargo-clif"); - if cfg!(windows) { - cargo_clif.set_extension("exe"); - } + cargo_clif.push(get_wrapper_file_name("cargo-clif", "bin", &self.target_triple)); let mut cmd = Command::new(cargo_clif); cmd.args(args); -- cgit 1.4.1-3-g733a5 From f7d8805a47f9b670403b43f056a96d3d4cc4fdc6 Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Fri, 25 Jun 2021 14:35:51 +0200 Subject: Fix `Ipv6Addr::is_global` to check for global reachability rather than global scope --- library/std/src/net/ip.rs | 95 ++++++++++++++++++++++++++++++++------ library/std/src/net/ip/tests.rs | 100 +++++++++++++++++++++++++++++++++++----- 2 files changed, 168 insertions(+), 27 deletions(-) diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index 438bae01b60..0b141efbc18 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -1349,13 +1349,33 @@ impl Ipv6Addr { u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets()) } - /// Returns [`true`] if the address appears to be globally routable. - /// - /// The following return [`false`]: - /// - /// - the loopback address - /// - link-local and unique local unicast addresses - /// - interface-, link-, realm-, admin- and site-local multicast addresses + /// Returns [`true`] if the address appears to be globally reachable + /// as specified by the [IANA IPv6 Special-Purpose Address Registry]. + /// Whether or not an address is practically reachable will depend on your network configuration. + /// + /// Most IPv6 addresses are globally reachable; + /// unless they are specifically defined as *not* globally reachable. + /// + /// Non-exhaustive list of notable addresses that are not globally reachable: + /// - The [unspecified address] ([`is_unspecified`](Ipv6Addr::is_unspecified)) + /// - The [loopback address] ([`is_loopback`](Ipv6Addr::is_loopback)) + /// - IPv4-mapped addresses + /// - Addresses reserved for benchmarking + /// - Addresses reserved for documentation ([`is_documentation`](Ipv6Addr::is_documentation)) + /// - Unique local addresses ([`is_unique_local`](Ipv6Addr::is_unique_local)) + /// - Unicast addresses with link-local scope ([`is_unicast_link_local`](Ipv6Addr::is_unicast_link_local)) + /// + /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv6 Special-Purpose Address Registry]. + /// + /// Note that an address having global scope is not the same as being globally reachable, + /// and there is no direct relation between the two concepts: There exist addresses with global scope + /// that are not globally reachable (for example unique local addresses), + /// and addresses that are globally reachable without having global scope + /// (multicast addresses with non-global scope). + /// + /// [IANA IPv6 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml + /// [unspecified address]: Ipv6Addr::UNSPECIFIED + /// [loopback address]: Ipv6Addr::LOCALHOST /// /// # Examples /// @@ -1364,20 +1384,65 @@ impl Ipv6Addr { /// /// use std::net::Ipv6Addr; /// - /// 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); + /// // Most IPv6 addresses are globally reachable: + /// assert_eq!(Ipv6Addr::new(0x26, 0, 0x1c9, 0, 0, 0xafc8, 0x10, 0x1).is_global(), true); + /// + /// // However some addresses have been assigned a special meaning + /// // that makes them not globally reachable. Some examples are: + /// + /// // The unspecified address (`::`) + /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_global(), false); + /// + /// // The loopback address (`::1`) + /// assert_eq!(Ipv6Addr::LOCALHOST.is_global(), false); + /// + /// // IPv4-mapped addresses (`::ffff:0:0/96`) + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), false); + /// + /// // Addresses reserved for benchmarking (`2001:2::/48`) + /// assert_eq!(Ipv6Addr::new(0x2001, 2, 0, 0, 0, 0, 0, 1,).is_global(), false); + /// + /// // Addresses reserved for documentation (`2001:db8::/32`) + /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1).is_global(), false); + /// + /// // Unique local addresses (`fc00::/7`) + /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 1).is_global(), false); + /// + /// // Unicast addresses with link-local scope (`fe80::/10`) + /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 1).is_global(), false); + /// + /// // For a complete overview see the IANA IPv6 Special-Purpose Address Registry. /// ``` #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] pub const fn is_global(&self) -> bool { - match self.multicast_scope() { - Some(Ipv6MulticastScope::Global) => true, - None => self.is_unicast_global(), - _ => false, - } + !(self.is_unspecified() + || self.is_loopback() + // IPv4-mapped Address (`::ffff:0:0/96`) + || matches!(self.segments(), [0, 0, 0, 0, 0, 0xffff, _, _]) + // IPv4-IPv6 Translat. (`64:ff9b:1::/48`) + || matches!(self.segments(), [0x64, 0xff9b, 1, _, _, _, _, _]) + // Discard-Only Address Block (`100::/64`) + || matches!(self.segments(), [0x100, 0, 0, 0, _, _, _, _]) + // IETF Protocol Assignments (`2001::/23`) + || (matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b < 0x200) + && !( + // Port Control Protocol Anycast (`2001:1::1`) + u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0001 + // Traversal Using Relays around NAT Anycast (`2001:1::2`) + || u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0002 + // AMT (`2001:3::/32`) + || matches!(self.segments(), [0x2001, 3, _, _, _, _, _, _]) + // AS112-v6 (`2001:4:112::/48`) + || matches!(self.segments(), [0x2001, 4, 0x112, _, _, _, _, _]) + // ORCHIDv2 (`2001:20::/28`) + || matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b >= 0x20 && b <= 0x2F) + )) + || self.is_documentation() + || self.is_unique_local() + || self.is_unicast_link_local()) } /// Returns [`true`] if this is a unique local address (`fc00::/7`). diff --git a/library/std/src/net/ip/tests.rs b/library/std/src/net/ip/tests.rs index 7956c6a25e4..0311efa8625 100644 --- a/library/std/src/net/ip/tests.rs +++ b/library/std/src/net/ip/tests.rs @@ -321,12 +321,12 @@ fn ip_properties() { check!("fe80:ffff::"); check!("febf:ffff::"); check!("fec0::", global); - check!("ff01::", multicast); - check!("ff02::", multicast); - check!("ff03::", multicast); - check!("ff04::", multicast); - check!("ff05::", multicast); - check!("ff08::", multicast); + check!("ff01::", global | multicast); + check!("ff02::", global | multicast); + check!("ff03::", global | multicast); + check!("ff04::", global | multicast); + check!("ff05::", global | multicast); + check!("ff08::", global | multicast); check!("ff0e::", global | multicast); check!("2001:db8:85a3::8a2e:370:7334", doc); check!("2001:2::ac32:23ff:21", global | benchmarking); @@ -609,6 +609,60 @@ fn ipv6_properties() { check!("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], global | unicast_global); + check!( + "::ffff:127.0.0.1", + &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x7f, 0, 0, 1], + unicast_global + ); + + check!( + "64:ff9b:1::", + &[0, 0x64, 0xff, 0x9b, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + unicast_global + ); + + check!("100::", &[0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global); + + check!("2001::", &[0x20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global); + + check!( + "2001:1::1", + &[0x20, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], + global | unicast_global + ); + + check!( + "2001:1::2", + &[0x20, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], + global | unicast_global + ); + + check!( + "2001:3::", + &[0x20, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + global | unicast_global + ); + + check!( + "2001:4:112::", + &[0x20, 1, 0, 4, 1, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + global | unicast_global + ); + + check!( + "2001:20::", + &[0x20, 1, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + global | unicast_global + ); + + check!("2001:30::", &[0x20, 1, 0, 0x30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global); + + check!( + "2001:200::", + &[0x20, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + global | unicast_global + ); + check!("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unique_local); check!( @@ -666,21 +720,37 @@ fn ipv6_properties() { check!( "ff01::", &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - multicast_interface_local + multicast_interface_local | global ); - check!("ff02::", &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], multicast_link_local); + check!( + "ff02::", + &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_link_local | global + ); - check!("ff03::", &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], multicast_realm_local); + check!( + "ff03::", + &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_realm_local | global + ); - check!("ff04::", &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], multicast_admin_local); + check!( + "ff04::", + &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_admin_local | global + ); - check!("ff05::", &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], multicast_site_local); + check!( + "ff05::", + &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_site_local | global + ); check!( "ff08::", &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - multicast_organization_local + multicast_organization_local | global ); check!( @@ -689,6 +759,12 @@ fn ipv6_properties() { multicast_global | global ); + check!( + "2001:2::ac32:23ff:21", + &[0x20, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0xac, 0x32, 0x23, 0xff, 0, 0x21], + unicast_global + ); + check!( "2001:db8:85a3::8a2e:370:7334", &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34], -- cgit 1.4.1-3-g733a5 From f2990648db66b969b89872d42771f83bbc5c7c7e Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Fri, 25 Jun 2021 21:31:14 +0200 Subject: Change `Ipv4Addr::is_global` to be in line with `Ipv6Addr::is_global` Rebasing off master --- library/std/src/net/ip.rs | 119 +++++++++++++++++++++++----------------------- 1 file changed, 60 insertions(+), 59 deletions(-) diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index 0b141efbc18..7bc1ad4b05b 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -631,25 +631,31 @@ impl Ipv4Addr { matches!(self.octets(), [169, 254, ..]) } - /// Returns [`true`] if the address appears to be globally routable. - /// See [iana-ipv4-special-registry][ipv4-sr]. + /// Returns [`true`] if the address appears to be globally reachable + /// as specified by the [IANA IPv4 Special-Purpose Address Registry]. + /// Whether or not an address is practically reachable will depend on your network configuration. + /// + /// Most IPv4 addresses are globally reachable; + /// unless they are specifically defined as *not* globally reachable. + /// + /// Non-exhaustive list of notable addresses that are not globally reachable: /// - /// The following return [`false`]: + /// - The [unspecified address] ([`is_unspecified`](Ipv4Addr::is_unspecified)) + /// - Addresses reserved for private use ([`is_private`](Ipv4Addr::is_private)) + /// - Addresses in the shared address space ([`is_shared`](Ipv4Addr::is_shared)) + /// - Loopback addresses ([`is_loopback`](Ipv4Addr::is_loopback)) + /// - Link-local addresses ([`is_link_local`](Ipv4Addr::is_link_local)) + /// - Addresses reserved for documentation ([`is_documentation`](Ipv4Addr::is_documentation)) + /// - Addresses reserved for benchmarking ([`is_benchmarking`](Ipv4Addr::is_benchmarking)) + /// - Reserved addresses ([`is_reserved`](Ipv4Addr::is_reserved)) + /// - The [broadcast address] ([`is_broadcast`](Ipv4Addr::is_broadcast)) /// - /// - private addresses (see [`Ipv4Addr::is_private()`]) - /// - the loopback address (see [`Ipv4Addr::is_loopback()`]) - /// - the link-local address (see [`Ipv4Addr::is_link_local()`]) - /// - the broadcast address (see [`Ipv4Addr::is_broadcast()`]) - /// - addresses used for documentation (see [`Ipv4Addr::is_documentation()`]) - /// - the unspecified address (see [`Ipv4Addr::is_unspecified()`]), and the whole - /// `0.0.0.0/8` block - /// - addresses reserved for future protocols, except - /// `192.0.0.9/32` and `192.0.0.10/32` which are globally routable - /// - addresses reserved for future use (see [`Ipv4Addr::is_reserved()`] - /// - addresses reserved for networking devices benchmarking (see - /// [`Ipv4Addr::is_benchmarking()`]) + /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv4 Special-Purpose Address Registry]. /// - /// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml + /// [IANA IPv4 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml + /// [unspecified address]: Ipv4Addr::UNSPECIFIED + /// [broadcast address]: Ipv4Addr::BROADCAST + /// /// # Examples /// @@ -658,71 +664,66 @@ impl Ipv4Addr { /// /// use std::net::Ipv4Addr; /// - /// // private addresses are not global + /// // Most IPv4 addresses are globally reachable: + /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true); + /// + /// // However some addresses have been assigned a special meaning + /// // that makes them not globally reachable. Some examples are: + /// + /// // The unspecified address (`0.0.0.0`) + /// assert_eq!(Ipv4Addr::UNSPECIFIED.is_global(), false); + /// + /// // Addresses reserved for private use (`10.0.0.0/8`, `172.16.0.0/12`, 192.168.0.0/16) /// 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); + /// // Addresses in the shared address space (`100.64.0.0/10`) + /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false); /// - /// // the loopback address is not global - /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_global(), false); + /// // The loopback addresses (`127.0.0.0/8`) + /// assert_eq!(Ipv4Addr::LOCALHOST.is_global(), false); /// - /// // link local addresses are not global + /// // Link-local addresses (`169.254.0.0/16`) /// 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 address space designated for documentation is not global + /// // Addresses reserved for documentation (`192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24`) /// 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); - /// - /// // 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 benchmarking (`198.18.0.0/15`) + /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false); /// - /// // addresses reserved for future use are not global + /// // Reserved addresses (`240.0.0.0/4`) /// 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); + /// // The broadcast address (`255.255.255.255`) + /// assert_eq!(Ipv4Addr::BROADCAST.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); + /// // For a complete overview see the IANA IPv4 Special-Purpose Address Registry. /// ``` #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] pub const 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 - // globally routable addresses in the 192.0.0.0/24 range. - if u32::from_be_bytes(self.octets()) == 0xc0000009 - || u32::from_be_bytes(self.octets()) == 0xc000000a - { - return true; - } - !self.is_private() - && !self.is_loopback() - && !self.is_link_local() - && !self.is_broadcast() - && !self.is_documentation() - && !self.is_shared() - // addresses reserved for future protocols (`192.0.0.0/24`) - && !(self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0) - && !self.is_reserved() - && !self.is_benchmarking() - // Make sure the address is not in 0.0.0.0/8 - && self.octets()[0] != 0 + !(self.octets()[0] == 0 // "This network" + || self.is_private() + || self.is_shared() + || self.is_loopback() + || self.is_link_local() + || (self.is_ietf_protocol_assignment() + && !( + // Port Control Protocol Anycast (`192.0.0.9`) + u32::from_be_bytes(self.octets()) == 0xc0000009 + // Traversal Using Relays around NAT Anycast (`192.0.0.10`) + || u32::from_be_bytes(self.octets()) == 0xc000000a + )) + || self.is_documentation() + || self.is_benchmarking() + || self.is_reserved() + || self.is_broadcast()) } /// Returns [`true`] if this address is part of the Shared Address Space defined in -- cgit 1.4.1-3-g733a5 From 3365b0631dad649ad9155c69cf9b6428e7b5228f Mon Sep 17 00:00:00 2001 From: Christopher Hotchkiss Date: Sat, 30 Jul 2022 11:37:16 -0400 Subject: Reincorporated changes from #87689 --- library/std/src/net/ip.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index 7bc1ad4b05b..ebbb69e7065 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -713,13 +713,8 @@ impl Ipv4Addr { || self.is_shared() || self.is_loopback() || self.is_link_local() - || (self.is_ietf_protocol_assignment() - && !( - // Port Control Protocol Anycast (`192.0.0.9`) - u32::from_be_bytes(self.octets()) == 0xc0000009 - // Traversal Using Relays around NAT Anycast (`192.0.0.10`) - || u32::from_be_bytes(self.octets()) == 0xc000000a - )) + // addresses reserved for future protocols (`192.0.0.0/24`) + ||(self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0) || self.is_documentation() || self.is_benchmarking() || self.is_reserved() -- cgit 1.4.1-3-g733a5 From 02443552c56c0b5d909ba3ddc653e686dff09d9c Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Sun, 31 Jul 2022 00:02:47 +0800 Subject: break out to one scope higher for let-else --- compiler/rustc_mir_build/src/build/block.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index 6875600129a..c52a7b187d5 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -1,6 +1,7 @@ use crate::build::matches::ArmHasGuard; use crate::build::ForGuard::OutsideGuard; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; +use rustc_middle::middle::region::Scope; use rustc_middle::thir::*; use rustc_middle::{mir::*, ty}; use rustc_span::Span; @@ -34,10 +35,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &stmts, expr, safety_mode, + region_scope, )) }) } else { - this.ast_block_stmts(destination, block, span, &stmts, expr, safety_mode) + this.ast_block_stmts( + destination, + block, + span, + &stmts, + expr, + safety_mode, + region_scope, + ) } }) }) @@ -51,6 +61,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { stmts: &[StmtId], expr: Option<&Expr<'tcx>>, safety_mode: BlockSafety, + region_scope: Scope, ) -> BlockAnd<()> { let this = self; @@ -73,6 +84,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mut let_scope_stack = Vec::with_capacity(8); let outer_source_scope = this.source_scope; let outer_in_scope_unsafe = this.in_scope_unsafe; + // This scope information is kept for breaking out of the current block in case + // one let-else pattern matching fails. + let mut last_remainder_scope = region_scope; this.update_source_scope_for_safety_mode(span, safety_mode); let source_info = this.source_info(span); @@ -132,7 +146,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { initializer_span, else_block, visibility_scope, - *remainder_scope, + last_remainder_scope, remainder_span, pattern, ) @@ -178,6 +192,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if let Some(source_scope) = visibility_scope { this.source_scope = source_scope; } + last_remainder_scope = *remainder_scope; } } -- cgit 1.4.1-3-g733a5 From f6590887df24f91a883da511d0a24d17ac4283e6 Mon Sep 17 00:00:00 2001 From: Christopher Hotchkiss Date: Sat, 30 Jul 2022 13:05:33 -0400 Subject: Original branch seems to have missed excluding the benchmark range from the globally reachable change --- library/std/src/net/ip.rs | 1 + library/std/src/net/ip/tests.rs | 10 ++-------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index ebbb69e7065..3c795f976f8 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -1635,6 +1635,7 @@ impl Ipv6Addr { && !self.is_unique_local() && !self.is_unspecified() && !self.is_documentation() + && !self.is_benchmarking() } /// Returns the address's multicast scope if the address is multicast. diff --git a/library/std/src/net/ip/tests.rs b/library/std/src/net/ip/tests.rs index 0311efa8625..f5051d65fc7 100644 --- a/library/std/src/net/ip/tests.rs +++ b/library/std/src/net/ip/tests.rs @@ -329,7 +329,7 @@ fn ip_properties() { check!("ff08::", global | multicast); check!("ff0e::", global | multicast); check!("2001:db8:85a3::8a2e:370:7334", doc); - check!("2001:2::ac32:23ff:21", global | benchmarking); + check!("2001:2::ac32:23ff:21", benchmarking); check!("102:304:506:708:90a:b0c:d0e:f10", global); } @@ -759,12 +759,6 @@ fn ipv6_properties() { multicast_global | global ); - check!( - "2001:2::ac32:23ff:21", - &[0x20, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0xac, 0x32, 0x23, 0xff, 0, 0x21], - unicast_global - ); - check!( "2001:db8:85a3::8a2e:370:7334", &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34], @@ -774,7 +768,7 @@ fn ipv6_properties() { check!( "2001:2::ac32:23ff:21", &[0x20, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0xac, 0x32, 0x23, 0xff, 0, 0x21], - global | unicast_global | benchmarking + benchmarking ); check!( -- cgit 1.4.1-3-g733a5 From aa2f4072f60c5c129a5597cc59ad908aa502868e Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 15:40:44 +0100 Subject: Use Windows Env vars in CI --- .github/workflows/main.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1a947d3551c..832572bcf35 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -164,14 +164,14 @@ jobs: - name: Test run: | # Enable backtraces for easier debugging - export RUST_BACKTRACE=1 + $Env:RUST_BACKTRACE=1 # Reduce amount of benchmark runs as they are slow - export COMPILE_RUNS=2 - export RUN_RUNS=2 + $Env:COMPILE_RUNS=2 + $Env:RUN_RUNS=2 # Enable extra checks - export CG_CLIF_ENABLE_VERIFIER=1 + $Env:CG_CLIF_ENABLE_VERIFIER=1 ./y.exe test -- cgit 1.4.1-3-g733a5 From 8ec3d20882f434b9cdbca5c8ed4f3630883b32aa Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 16:35:35 +0100 Subject: Fix test.regex test --- build_system/tests.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/build_system/tests.rs b/build_system/tests.rs index 20d600effd3..22c8c8a4605 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -186,7 +186,6 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ let mut build_cmd = runner.cargo_command(["build", "--example", "shootout-regex-dna", "--target", &runner.target_triple]); build_cmd.env("RUSTFLAGS", lint_rust_flags.clone()); - spawn_and_wait(build_cmd); if runner.host_triple == runner.target_triple { @@ -233,11 +232,18 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ runner.in_dir(["regex"], |runner| { runner.run_cargo(["clean"]); + // newer aho_corasick versions throw a deprecation warning + let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags); + if runner.host_triple == runner.target_triple { - runner.run_cargo(["test", "--tests", "--", "--exclude-should-panic", "--test-threads", "1", "-Zunstable-options", "-q"]); + let mut run_cmd = runner.cargo_command(["test", "--tests", "--", "--exclude-should-panic", "--test-threads", "1", "-Zunstable-options", "-q"]); + run_cmd.env("RUSTFLAGS", lint_rust_flags); + spawn_and_wait(run_cmd); } else { eprintln!("Cross-Compiling: Not running tests"); - runner.run_cargo(["build", "--tests", "--target", &runner.target_triple]); + let mut build_cmd = runner.cargo_command(["build", "--tests", "--target", &runner.target_triple]); + build_cmd.env("RUSTFLAGS", lint_rust_flags.clone()); + spawn_and_wait(build_cmd); } }); }), -- cgit 1.4.1-3-g733a5 From f8747f0a53dc5b1284fab7610df39f4861b311e4 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 20:24:04 +0100 Subject: Fix aarch64 cross compilation --- build_system/tests.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/build_system/tests.rs b/build_system/tests.rs index 22c8c8a4605..5c69beeaab5 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -322,7 +322,7 @@ struct TestRunner { out_dir: PathBuf, jit_supported: bool, rust_flags: String, - run_wrapper: String, + run_wrapper: Vec, host_triple: String, target_triple: String, } @@ -339,18 +339,18 @@ impl TestRunner { let jit_supported = target_triple.contains("x86_64") && is_native; let mut rust_flags = env::var("RUSTFLAGS").ok().unwrap_or("".to_string()); - let mut run_wrapper = String::new(); + let mut run_wrapper = Vec::new(); if !is_native { match target_triple.as_str() { "aarch64-unknown-linux-gnu" => { // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu. - rust_flags = format!("-Clinker=aarch64-linux-gnu-gcc {}", rust_flags); - run_wrapper = "qemu-aarch64 -L /usr/aarch64-linux-gnu".to_string(); + rust_flags = format!("-Clinker=aarch64-linux-gnu-gcc{}", rust_flags); + run_wrapper = vec!["qemu-aarch64", "-L", "/usr/aarch64-linux-gnu"]; }, "x86_64-pc-windows-gnu" => { // We are cross-compiling for Windows. Run tests in wine. - run_wrapper = "wine".to_string(); + run_wrapper = vec!["wine"]; } _ => { println!("Unknown non-native platform"); @@ -368,7 +368,7 @@ impl TestRunner { out_dir, jit_supported, rust_flags, - run_wrapper, + run_wrapper: run_wrapper.iter().map(|s| s.to_string()).collect(), host_triple, target_triple, } @@ -446,7 +446,7 @@ impl TestRunner { // Prepend the RUN_WRAPPER's if !self.run_wrapper.is_empty() { - full_cmd.push(self.run_wrapper.clone()); + full_cmd.extend(self.run_wrapper.iter().cloned()); } full_cmd.push({ @@ -459,6 +459,7 @@ impl TestRunner { full_cmd.push(arg.to_string()); } + println!("full_CMD: {:?}", full_cmd); let mut cmd_iter = full_cmd.into_iter(); let first = cmd_iter.next().unwrap(); -- cgit 1.4.1-3-g733a5 From 393613439a09c7d2c36832eb532a13f140a46552 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 17:16:10 +0100 Subject: Fix some cross compilation scenarios in test runner --- build_system/build_sysroot.rs | 4 ++-- build_system/tests.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index cd3216cd624..ed1c04808c5 100644 --- a/build_system/build_sysroot.rs +++ b/build_system/build_sysroot.rs @@ -23,7 +23,7 @@ pub(crate) fn build_sysroot( fs::create_dir_all(target_dir.join("lib")).unwrap(); // Copy the backend - let cg_clif_dylib = get_file_name("rustc_codegen_cranelift", "dylib", target_triple); + let cg_clif_dylib = get_file_name("rustc_codegen_cranelift", "dylib", host_triple); let cg_clif_dylib_path = target_dir .join(if cfg!(windows) { // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the @@ -37,7 +37,7 @@ pub(crate) fn build_sysroot( // Build and copy rustc and cargo wrappers for wrapper in ["rustc-clif", "cargo-clif"] { - let wrapper_name = get_wrapper_file_name(wrapper, "bin", target_triple); + let wrapper_name = get_wrapper_file_name(wrapper, "bin", host_triple); let mut build_cargo_wrapper_cmd = Command::new("rustc"); build_cargo_wrapper_cmd diff --git a/build_system/tests.rs b/build_system/tests.rs index 5c69beeaab5..bc13066b020 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -414,7 +414,7 @@ impl TestRunner { { let mut rustc_clif = self.root_dir.clone(); rustc_clif.push("build"); - rustc_clif.push(get_wrapper_file_name("rustc-clif", "bin", &self.target_triple)); + rustc_clif.push(get_wrapper_file_name("rustc-clif", "bin", &self.host_triple)); let mut cmd = Command::new(rustc_clif); if !self.rust_flags.is_empty() { @@ -476,7 +476,7 @@ impl TestRunner { { let mut cargo_clif = self.root_dir.clone(); cargo_clif.push("build"); - cargo_clif.push(get_wrapper_file_name("cargo-clif", "bin", &self.target_triple)); + cargo_clif.push(get_wrapper_file_name("cargo-clif", "bin", &self.host_triple)); let mut cmd = Command::new(cargo_clif); cmd.args(args); -- cgit 1.4.1-3-g733a5 From 6ea108bae3358ffee78fcdfb4b442dd8d81b29b4 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 21:08:21 +0100 Subject: Split flags whitespace This is probably the wrong way to do this... --- build_system/tests.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/build_system/tests.rs b/build_system/tests.rs index bc13066b020..e4a776259c0 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -417,9 +417,7 @@ impl TestRunner { rustc_clif.push(get_wrapper_file_name("rustc-clif", "bin", &self.host_triple)); let mut cmd = Command::new(rustc_clif); - if !self.rust_flags.is_empty() { - cmd.arg(&self.rust_flags); - } + cmd.args(self.rust_flags.split_whitespace()); cmd.arg("-L"); cmd.arg(format!("crate={}", self.out_dir.display())); cmd.arg("--out-dir"); -- cgit 1.4.1-3-g733a5 From 78372d6b411523bc9d1f081ff3951d39367e8f5f Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 21:08:59 +0100 Subject: Log cloned regex output --- .github/workflows/main.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 832572bcf35..a75c4f97529 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -79,6 +79,10 @@ jobs: git config --global user.email "user@example.com" git config --global user.name "User" ./y.rs prepare + + + - name: log expected output + run: cat -e regex/examples/regexdna-output.txt - name: Build without unstable features env: -- cgit 1.4.1-3-g733a5 From 905834232bf7da7ae2b282806b9de4f102040d1d Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 30 Jul 2022 22:44:23 +0200 Subject: Simplify implementation for par_for_each_module. --- compiler/rustc_middle/src/hir/map/mod.rs | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 47b04c33ec1..fa64b98d62f 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -491,7 +491,7 @@ impl<'hir> Map<'hir> { self.tcx.hir_crate_items(()).body_owners.iter().copied() } - pub fn par_body_owners(self, f: F) { + pub fn par_body_owners(self, f: impl Fn(LocalDefId) + Sync + Send) { par_for_each_in(&self.tcx.hir_crate_items(()).body_owners[..], |&def_id| f(def_id)); } @@ -624,25 +624,10 @@ impl<'hir> Map<'hir> { } } - #[cfg(not(parallel_compiler))] #[inline] - pub fn par_for_each_module(self, f: impl Fn(LocalDefId)) { - self.for_each_module(f) - } - - #[cfg(parallel_compiler)] - pub fn par_for_each_module(self, f: impl Fn(LocalDefId) + Sync) { - use rustc_data_structures::sync::{par_iter, ParallelIterator}; - par_iter_submodules(self.tcx, CRATE_DEF_ID, &f); - - fn par_iter_submodules(tcx: TyCtxt<'_>, module: LocalDefId, f: &F) - where - F: Fn(LocalDefId) + Sync, - { - (*f)(module); - let items = tcx.hir_module_items(module); - par_iter(&items.submodules[..]).for_each(|&sm| par_iter_submodules(tcx, sm, f)); - } + pub fn par_for_each_module(self, f: impl Fn(LocalDefId) + Sync + Send) { + let crate_items = self.tcx.hir_crate_items(()); + par_for_each_in(&crate_items.submodules[..], |module| f(*module)) } /// Returns an iterator for the nodes in the ancestor tree of the `current_id` -- cgit 1.4.1-3-g733a5 From 4c5ec30342fdf15d939d714f6292fd307994d535 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 30 Jul 2022 22:44:49 +0200 Subject: Inline a few short methods. --- compiler/rustc_middle/src/hir/map/mod.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index fa64b98d62f..127c8b58cc7 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -146,10 +146,12 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> { } impl<'hir> Map<'hir> { + #[inline] pub fn krate(self) -> &'hir Crate<'hir> { self.tcx.hir_crate(()) } + #[inline] pub fn root_module(self) -> &'hir Mod<'hir> { match self.tcx.hir_owner(CRATE_DEF_ID).map(|o| o.node) { Some(OwnerNode::Crate(item)) => item, @@ -157,14 +159,17 @@ impl<'hir> Map<'hir> { } } + #[inline] pub fn items(self) -> impl Iterator + 'hir { self.tcx.hir_crate_items(()).items.iter().copied() } + #[inline] pub fn module_items(self, module: LocalDefId) -> impl Iterator + 'hir { self.tcx.hir_module_items(module).items() } + #[inline] pub fn par_for_each_item(self, f: impl Fn(ItemId) + Sync + Send) { par_for_each_in(&self.tcx.hir_crate_items(()).items[..], |id| f(*id)); } @@ -487,10 +492,12 @@ impl<'hir> Map<'hir> { /// Returns an iterator of the `DefId`s for all body-owners in this /// crate. If you would prefer to iterate over the bodies /// themselves, you can do `self.hir().krate().body_ids.iter()`. + #[inline] pub fn body_owners(self) -> impl Iterator + 'hir { self.tcx.hir_crate_items(()).body_owners.iter().copied() } + #[inline] pub fn par_body_owners(self, f: impl Fn(LocalDefId) + Sync + Send) { par_for_each_in(&self.tcx.hir_crate_items(()).body_owners[..], |&def_id| f(def_id)); } @@ -632,12 +639,14 @@ impl<'hir> Map<'hir> { /// Returns an iterator for the nodes in the ancestor tree of the `current_id` /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`. + #[inline] pub fn parent_iter(self, current_id: HirId) -> ParentHirIterator<'hir> { ParentHirIterator { current_id, map: self } } /// Returns an iterator for the nodes in the ancestor tree of the `current_id` /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`. + #[inline] pub fn parent_owner_iter(self, current_id: HirId) -> ParentOwnerIterator<'hir> { ParentOwnerIterator { current_id, map: self } } -- cgit 1.4.1-3-g733a5 From bec651ef47efae5732e7b17c4d49e2718544d4c8 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 22:05:39 +0100 Subject: Compare lines iterator instead of full output This avoids differences in line endings. --- .github/workflows/main.yml | 4 ---- build_system/tests.rs | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a75c4f97529..832572bcf35 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -79,10 +79,6 @@ jobs: git config --global user.email "user@example.com" git config --global user.name "User" ./y.rs prepare - - - - name: log expected output - run: cat -e regex/examples/regexdna-output.txt - name: Build without unstable features env: diff --git a/build_system/tests.rs b/build_system/tests.rs index e4a776259c0..2c96c5cc175 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -206,7 +206,8 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ .join("\r\n"); - if output != expected { + let output_matches = expected.lines().eq(output.lines()); + if !output_matches { let res_path = PathBuf::from("res.txt"); fs::write(&res_path, &output).unwrap(); @@ -457,7 +458,6 @@ impl TestRunner { full_cmd.push(arg.to_string()); } - println!("full_CMD: {:?}", full_cmd); let mut cmd_iter = full_cmd.into_iter(); let first = cmd_iter.next().unwrap(); -- cgit 1.4.1-3-g733a5 From 2f1380036cff86b97de98434b5e59592624d4d54 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 22:32:06 +0100 Subject: Cleanup meaningless changes --- build_system/build_backend.rs | 2 +- build_system/mod.rs | 4 ++-- build_system/prepare.rs | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build_system/build_backend.rs b/build_system/build_backend.rs index ddc099b5388..48faec8bc4b 100644 --- a/build_system/build_backend.rs +++ b/build_system/build_backend.rs @@ -39,5 +39,5 @@ pub(crate) fn build_backend( eprintln!("[BUILD] rustc_codegen_cranelift"); super::utils::spawn_and_wait(cmd); - Path::new("target").join(&host_triple).join(&channel) + Path::new("target").join(host_triple).join(channel) } diff --git a/build_system/mod.rs b/build_system/mod.rs index 0124d47de75..3a6d58a2a6d 100644 --- a/build_system/mod.rs +++ b/build_system/mod.rs @@ -73,7 +73,7 @@ pub fn main() { eprintln!("Switch to the MinGW toolchain for Windows support."); eprintln!("Hint: You can use `rustup set default-host x86_64-pc-windows-gnu` to"); eprintln!("set the global default target to MinGW"); - // process::exit(1); + process::exit(1); } @@ -83,7 +83,7 @@ pub fn main() { if args.next().is_some() { arg_error!("./y.rs prepare doesn't expect arguments"); } - prepare::prepare(&target_triple); + prepare::prepare(&host_triple); process::exit(0); } Some("build") => Command::Build, diff --git a/build_system/prepare.rs b/build_system/prepare.rs index 4580c4b6549..b499aaa703c 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -8,7 +8,7 @@ use std::process::Command; use super::rustc_info::{get_file_name, get_rustc_path, get_rustc_version}; use super::utils::{copy_dir_recursively, spawn_and_wait}; -pub(crate) fn prepare(target_triple: &str) { +pub(crate) fn prepare(host_triple: &str) { prepare_sysroot(); eprintln!("[INSTALL] hyperfine"); @@ -49,8 +49,8 @@ pub(crate) fn prepare(target_triple: &str) { build_cmd.arg("build").env_remove("CARGO_TARGET_DIR").current_dir("simple-raytracer"); spawn_and_wait(build_cmd); fs::copy( - Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin", target_triple)), - Path::new("simple-raytracer").join(get_file_name("raytracer_cg_llvm", "bin", target_triple)), + Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin", host_triple)), + Path::new("simple-raytracer").join(get_file_name("raytracer_cg_llvm", "bin", host_triple)), ) .unwrap(); } -- cgit 1.4.1-3-g733a5 From 5d7936650d174515730458b29b83e99153365d89 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 22:58:34 +0100 Subject: Don't run tests on Windows CI --- .github/workflows/main.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 832572bcf35..e8897e9ae81 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -159,21 +159,19 @@ jobs: ./y.exe prepare - name: Build - run: ./y.exe build - - - name: Test + #name: Test run: | # Enable backtraces for easier debugging - $Env:RUST_BACKTRACE=1 + #$Env:RUST_BACKTRACE=1 # Reduce amount of benchmark runs as they are slow - $Env:COMPILE_RUNS=2 - $Env:RUN_RUNS=2 + #$Env:COMPILE_RUNS=2 + #$Env:RUN_RUNS=2 # Enable extra checks - $Env:CG_CLIF_ENABLE_VERIFIER=1 + #$Env:CG_CLIF_ENABLE_VERIFIER=1 - ./y.exe test + ./y.exe build - name: Package prebuilt cg_clif # don't use compression as xzip isn't supported by tar on windows and bzip2 hangs -- cgit 1.4.1-3-g733a5 From f588bfa0956dbd7880c08a22c612e9831df2e3d8 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 23:04:59 +0100 Subject: Assume host target in get_file_name --- build_system/build_sysroot.rs | 4 +-- build_system/mod.rs | 58 +++++++++++++++++++++---------------------- build_system/prepare.rs | 6 ++--- build_system/rustc_info.rs | 8 +++--- build_system/tests.rs | 4 +-- 5 files changed, 38 insertions(+), 42 deletions(-) diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index ed1c04808c5..6e4b57cf4d3 100644 --- a/build_system/build_sysroot.rs +++ b/build_system/build_sysroot.rs @@ -23,7 +23,7 @@ pub(crate) fn build_sysroot( fs::create_dir_all(target_dir.join("lib")).unwrap(); // Copy the backend - let cg_clif_dylib = get_file_name("rustc_codegen_cranelift", "dylib", host_triple); + let cg_clif_dylib = get_file_name("rustc_codegen_cranelift", "dylib"); let cg_clif_dylib_path = target_dir .join(if cfg!(windows) { // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the @@ -37,7 +37,7 @@ pub(crate) fn build_sysroot( // Build and copy rustc and cargo wrappers for wrapper in ["rustc-clif", "cargo-clif"] { - let wrapper_name = get_wrapper_file_name(wrapper, "bin", host_triple); + let wrapper_name = get_wrapper_file_name(wrapper, "bin"); let mut build_cargo_wrapper_cmd = Command::new("rustc"); build_cargo_wrapper_cmd diff --git a/build_system/mod.rs b/build_system/mod.rs index 3a6d58a2a6d..4772a5a7778 100644 --- a/build_system/mod.rs +++ b/build_system/mod.rs @@ -48,42 +48,13 @@ pub fn main() { // The target dir is expected in the default location. Guard against the user changing it. env::set_var("CARGO_TARGET_DIR", "target"); - - let host_triple = if let Ok(host_triple) = std::env::var("HOST_TRIPLE") { - host_triple - } else if let Some(host_triple) = config::get_value("host") { - host_triple - } else { - rustc_info::get_host_triple() - }; - let target_triple = if let Ok(target_triple) = std::env::var("TARGET_TRIPLE") { - if target_triple != "" { - target_triple - } else { - host_triple.clone() // Empty target triple can happen on GHA - } - } else if let Some(target_triple) = config::get_value("target") { - target_triple - } else { - host_triple.clone() - }; - - if target_triple.ends_with("-msvc") { - eprintln!("The MSVC toolchain is not yet supported by rustc_codegen_cranelift."); - eprintln!("Switch to the MinGW toolchain for Windows support."); - eprintln!("Hint: You can use `rustup set default-host x86_64-pc-windows-gnu` to"); - eprintln!("set the global default target to MinGW"); - process::exit(1); - } - - let mut args = env::args().skip(1); let command = match args.next().as_deref() { Some("prepare") => { if args.next().is_some() { arg_error!("./y.rs prepare doesn't expect arguments"); } - prepare::prepare(&host_triple); + prepare::prepare(); process::exit(0); } Some("build") => Command::Build, @@ -124,6 +95,33 @@ pub fn main() { } target_dir = std::env::current_dir().unwrap().join(target_dir); + let host_triple = if let Ok(host_triple) = std::env::var("HOST_TRIPLE") { + host_triple + } else if let Some(host_triple) = config::get_value("host") { + host_triple + } else { + rustc_info::get_host_triple() + }; + let target_triple = if let Ok(target_triple) = std::env::var("TARGET_TRIPLE") { + if target_triple != "" { + target_triple + } else { + host_triple.clone() // Empty target triple can happen on GHA + } + } else if let Some(target_triple) = config::get_value("target") { + target_triple + } else { + host_triple.clone() + }; + + if target_triple.ends_with("-msvc") { + eprintln!("The MSVC toolchain is not yet supported by rustc_codegen_cranelift."); + eprintln!("Switch to the MinGW toolchain for Windows support."); + eprintln!("Hint: You can use `rustup set default-host x86_64-pc-windows-gnu` to"); + eprintln!("set the global default target to MinGW"); + process::exit(1); + } + let cg_clif_build_dir = build_backend::build_backend(channel, &host_triple, use_unstable_features); match command { Command::Test => { diff --git a/build_system/prepare.rs b/build_system/prepare.rs index b499aaa703c..7e0fd182d98 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -8,7 +8,7 @@ use std::process::Command; use super::rustc_info::{get_file_name, get_rustc_path, get_rustc_version}; use super::utils::{copy_dir_recursively, spawn_and_wait}; -pub(crate) fn prepare(host_triple: &str) { +pub(crate) fn prepare() { prepare_sysroot(); eprintln!("[INSTALL] hyperfine"); @@ -49,8 +49,8 @@ pub(crate) fn prepare(host_triple: &str) { build_cmd.arg("build").env_remove("CARGO_TARGET_DIR").current_dir("simple-raytracer"); spawn_and_wait(build_cmd); fs::copy( - Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin", host_triple)), - Path::new("simple-raytracer").join(get_file_name("raytracer_cg_llvm", "bin", host_triple)), + Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin")), + Path::new("simple-raytracer").join(get_file_name("raytracer_cg_llvm", "bin")), ) .unwrap(); } diff --git a/build_system/rustc_info.rs b/build_system/rustc_info.rs index 63e1d16ead6..913b589afcc 100644 --- a/build_system/rustc_info.rs +++ b/build_system/rustc_info.rs @@ -43,7 +43,7 @@ pub(crate) fn get_default_sysroot() -> PathBuf { Path::new(String::from_utf8(default_sysroot).unwrap().trim()).to_owned() } -pub(crate) fn get_file_name(crate_name: &str, crate_type: &str, target: &str) -> String { +pub(crate) fn get_file_name(crate_name: &str, crate_type: &str) -> String { let file_name = Command::new("rustc") .stderr(Stdio::inherit()) .args(&[ @@ -51,8 +51,6 @@ pub(crate) fn get_file_name(crate_name: &str, crate_type: &str, target: &str) -> crate_name, "--crate-type", crate_type, - "--target", - target, "--print", "file-names", "-", @@ -69,8 +67,8 @@ pub(crate) fn get_file_name(crate_name: &str, crate_type: &str, target: &str) -> /// Similar to `get_file_name`, but converts any dashes (`-`) in the `crate_name` to /// underscores (`_`). This is specially made for the the rustc and cargo wrappers /// which have a dash in the name, and that is not allowed in a crate name. -pub(crate) fn get_wrapper_file_name(crate_name: &str, crate_type: &str, target: &str) -> String { +pub(crate) fn get_wrapper_file_name(crate_name: &str, crate_type: &str) -> String { let crate_name = crate_name.replace('-', "_"); - let wrapper_name = get_file_name(&crate_name, crate_type, target); + let wrapper_name = get_file_name(&crate_name, crate_type); wrapper_name.replace('_', "-") } diff --git a/build_system/tests.rs b/build_system/tests.rs index 2c96c5cc175..2b4ae39a75e 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -415,7 +415,7 @@ impl TestRunner { { let mut rustc_clif = self.root_dir.clone(); rustc_clif.push("build"); - rustc_clif.push(get_wrapper_file_name("rustc-clif", "bin", &self.host_triple)); + rustc_clif.push(get_wrapper_file_name("rustc-clif", "bin")); let mut cmd = Command::new(rustc_clif); cmd.args(self.rust_flags.split_whitespace()); @@ -474,7 +474,7 @@ impl TestRunner { { let mut cargo_clif = self.root_dir.clone(); cargo_clif.push("build"); - cargo_clif.push(get_wrapper_file_name("cargo-clif", "bin", &self.host_triple)); + cargo_clif.push(get_wrapper_file_name("cargo-clif", "bin")); let mut cmd = Command::new(cargo_clif); cmd.args(args); -- cgit 1.4.1-3-g733a5 From d489fb9a59338051e1f488c87d8ee55bd25e0208 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 23:07:03 +0100 Subject: Don't pass RUSTFLAGS to rustc in tests --- build_system/tests.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/build_system/tests.rs b/build_system/tests.rs index 2b4ae39a75e..f6f3f4831e1 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -425,7 +425,6 @@ impl TestRunner { cmd.arg(format!("{}", self.out_dir.display())); cmd.arg("-Cdebuginfo=2"); cmd.args(args); - cmd.env("RUSTFLAGS", &self.rust_flags); cmd } -- cgit 1.4.1-3-g733a5 From 0db9094231138fb29895fc181d534a2a547d168a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 31 Jul 2022 10:15:56 +0000 Subject: Rustfmt --- build_system/build_sysroot.rs | 2 +- build_system/mod.rs | 7 +- build_system/tests.rs | 234 ++++++++++++++++++++++++++++++++---------- build_system/utils.rs | 2 +- 4 files changed, 187 insertions(+), 58 deletions(-) diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index 6e4b57cf4d3..7e205b0fd0b 100644 --- a/build_system/build_sysroot.rs +++ b/build_system/build_sysroot.rs @@ -2,7 +2,7 @@ use std::fs; use std::path::{Path, PathBuf}; use std::process::{self, Command}; -use super::rustc_info::{get_file_name, get_wrapper_file_name, get_rustc_version}; +use super::rustc_info::{get_file_name, get_rustc_version, get_wrapper_file_name}; use super::utils::{spawn_and_wait, try_hard_link}; use super::SysrootKind; diff --git a/build_system/mod.rs b/build_system/mod.rs index 4772a5a7778..8c7d05993a5 100644 --- a/build_system/mod.rs +++ b/build_system/mod.rs @@ -7,8 +7,8 @@ mod build_sysroot; mod config; mod prepare; mod rustc_info; -mod utils; mod tests; +mod utils; fn usage() { eprintln!("Usage:"); @@ -122,7 +122,8 @@ pub fn main() { process::exit(1); } - let cg_clif_build_dir = build_backend::build_backend(channel, &host_triple, use_unstable_features); + let cg_clif_build_dir = + build_backend::build_backend(channel, &host_triple, use_unstable_features); match command { Command::Test => { tests::run_tests( @@ -133,7 +134,7 @@ pub fn main() { &host_triple, &target_triple, ); - }, + } Command::Build => { build_sysroot::build_sysroot( channel, diff --git a/build_system/tests.rs b/build_system/tests.rs index f6f3f4831e1..3f225b4efa2 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -22,85 +22,195 @@ impl TestCase { const NO_SYSROOT_SUITE: &[TestCase] = &[ TestCase::new("build.mini_core", &|runner| { - runner.run_rustc(["example/mini_core.rs", "--crate-name", "mini_core", "--crate-type", "lib,dylib", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/mini_core.rs", + "--crate-name", + "mini_core", + "--crate-type", + "lib,dylib", + "--target", + &runner.target_triple, + ]); }), - TestCase::new("build.example", &|runner| { - runner.run_rustc(["example/example.rs", "--crate-type", "lib", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/example.rs", + "--crate-type", + "lib", + "--target", + &runner.target_triple, + ]); }), - TestCase::new("jit.mini_core_hello_world", &|runner| { - let mut jit_cmd = runner.rustc_command(["-Zunstable-options", "-Cllvm-args=mode=jit", "-Cprefer-dynamic", "example/mini_core_hello_world.rs", "--cfg", "jit", "--target", &runner.host_triple]); + let mut jit_cmd = runner.rustc_command([ + "-Zunstable-options", + "-Cllvm-args=mode=jit", + "-Cprefer-dynamic", + "example/mini_core_hello_world.rs", + "--cfg", + "jit", + "--target", + &runner.host_triple, + ]); jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd"); spawn_and_wait(jit_cmd); eprintln!("[JIT-lazy] mini_core_hello_world"); - let mut jit_cmd = runner.rustc_command(["-Zunstable-options", "-Cllvm-args=mode=jit-lazy", "-Cprefer-dynamic", "example/mini_core_hello_world.rs", "--cfg", "jit", "--target", &runner.host_triple]); + let mut jit_cmd = runner.rustc_command([ + "-Zunstable-options", + "-Cllvm-args=mode=jit-lazy", + "-Cprefer-dynamic", + "example/mini_core_hello_world.rs", + "--cfg", + "jit", + "--target", + &runner.host_triple, + ]); jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd"); spawn_and_wait(jit_cmd); }), - TestCase::new("aot.mini_core_hello_world", &|runner| { - runner.run_rustc(["example/mini_core_hello_world.rs", "--crate-name", "mini_core_hello_world", "--crate-type", "bin", "-g", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/mini_core_hello_world.rs", + "--crate-name", + "mini_core_hello_world", + "--crate-type", + "bin", + "-g", + "--target", + &runner.target_triple, + ]); runner.run_out_command("mini_core_hello_world", ["abc", "bcd"]); }), ]; - const BASE_SYSROOT_SUITE: &[TestCase] = &[ TestCase::new("aot.arbitrary_self_types_pointers_and_wrappers", &|runner| { - runner.run_rustc(["example/arbitrary_self_types_pointers_and_wrappers.rs", "--crate-name", "arbitrary_self_types_pointers_and_wrappers", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/arbitrary_self_types_pointers_and_wrappers.rs", + "--crate-name", + "arbitrary_self_types_pointers_and_wrappers", + "--crate-type", + "bin", + "--target", + &runner.target_triple, + ]); runner.run_out_command("arbitrary_self_types_pointers_and_wrappers", []); }), - TestCase::new("aot.issue_91827_extern_types", &|runner| { - runner.run_rustc(["example/issue-91827-extern-types.rs", "--crate-name", "issue_91827_extern_types", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/issue-91827-extern-types.rs", + "--crate-name", + "issue_91827_extern_types", + "--crate-type", + "bin", + "--target", + &runner.target_triple, + ]); runner.run_out_command("issue_91827_extern_types", []); }), - TestCase::new("build.alloc_system", &|runner| { - runner.run_rustc(["example/alloc_system.rs", "--crate-type", "lib", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/alloc_system.rs", + "--crate-type", + "lib", + "--target", + &runner.target_triple, + ]); }), - TestCase::new("aot.alloc_example", &|runner| { - runner.run_rustc(["example/alloc_example.rs", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/alloc_example.rs", + "--crate-type", + "bin", + "--target", + &runner.target_triple, + ]); runner.run_out_command("alloc_example", []); }), - TestCase::new("jit.std_example", &|runner| { - runner.run_rustc(["-Zunstable-options", "-Cllvm-args=mode=jit", "-Cprefer-dynamic", "example/std_example.rs", "--target", &runner.host_triple]); + runner.run_rustc([ + "-Zunstable-options", + "-Cllvm-args=mode=jit", + "-Cprefer-dynamic", + "example/std_example.rs", + "--target", + &runner.host_triple, + ]); eprintln!("[JIT-lazy] std_example"); - runner.run_rustc(["-Zunstable-options", "-Cllvm-args=mode=jit-lazy", "-Cprefer-dynamic", "example/std_example.rs", "--target", &runner.host_triple]); + runner.run_rustc([ + "-Zunstable-options", + "-Cllvm-args=mode=jit-lazy", + "-Cprefer-dynamic", + "example/std_example.rs", + "--target", + &runner.host_triple, + ]); }), - TestCase::new("aot.std_example", &|runner| { - runner.run_rustc(["example/std_example.rs", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/std_example.rs", + "--crate-type", + "bin", + "--target", + &runner.target_triple, + ]); runner.run_out_command("std_example", ["arg"]); }), - TestCase::new("aot.dst_field_align", &|runner| { - runner.run_rustc(["example/dst-field-align.rs", "--crate-name", "dst_field_align", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/dst-field-align.rs", + "--crate-name", + "dst_field_align", + "--crate-type", + "bin", + "--target", + &runner.target_triple, + ]); runner.run_out_command("dst_field_align", []); }), - TestCase::new("aot.subslice-patterns-const-eval", &|runner| { - runner.run_rustc(["example/subslice-patterns-const-eval.rs", "--crate-type", "bin", "-Cpanic=abort", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/subslice-patterns-const-eval.rs", + "--crate-type", + "bin", + "-Cpanic=abort", + "--target", + &runner.target_triple, + ]); runner.run_out_command("subslice-patterns-const-eval", []); }), - TestCase::new("aot.track-caller-attribute", &|runner| { - runner.run_rustc(["example/track-caller-attribute.rs", "--crate-type", "bin", "-Cpanic=abort", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/track-caller-attribute.rs", + "--crate-type", + "bin", + "-Cpanic=abort", + "--target", + &runner.target_triple, + ]); runner.run_out_command("track-caller-attribute", []); }), - TestCase::new("aot.float-minmax-pass", &|runner| { - runner.run_rustc(["example/float-minmax-pass.rs", "--crate-type", "bin", "-Cpanic=abort", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/float-minmax-pass.rs", + "--crate-type", + "bin", + "-Cpanic=abort", + "--target", + &runner.target_triple, + ]); runner.run_out_command("float-minmax-pass", []); }), - TestCase::new("aot.mod_bench", &|runner| { - runner.run_rustc(["example/mod_bench.rs", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/mod_bench.rs", + "--crate-type", + "bin", + "--target", + &runner.target_triple, + ]); runner.run_out_command("mod_bench", []); }), ]; @@ -115,11 +225,16 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ runner.run_cargo(["test", "--workspace"]); } else { eprintln!("[AOT] rust-random/rand"); - runner.run_cargo(["build", "--workspace", "--target", &runner.target_triple, "--tests"]); + runner.run_cargo([ + "build", + "--workspace", + "--target", + &runner.target_triple, + "--tests", + ]); } }); }), - TestCase::new("bench.simple-raytracer", &|runner| { runner.in_dir(["simple-raytracer"], |runner| { let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()); @@ -143,10 +258,9 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ bench_compile.arg(format!("{:?}", runner.cargo_command(["build"]))); spawn_and_wait(bench_compile); - - eprintln!("[BENCH RUN] ebobby/simple-raytracer"); - fs::copy(PathBuf::from("./target/debug/main"), PathBuf::from("raytracer_cg_clif")).unwrap(); + fs::copy(PathBuf::from("./target/debug/main"), PathBuf::from("raytracer_cg_clif")) + .unwrap(); let mut bench_run = Command::new("hyperfine"); bench_run.arg("--runs"); @@ -163,7 +277,6 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ } }); }), - TestCase::new("test.libcore", &|runner| { runner.in_dir(["build_sysroot", "sysroot_src", "library", "core", "tests"], |runner| { runner.run_cargo(["clean"]); @@ -176,7 +289,6 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ } }); }), - TestCase::new("test.regex-shootout-regex-dna", &|runner| { runner.in_dir(["regex"], |runner| { runner.run_cargo(["clean"]); @@ -184,28 +296,40 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ // newer aho_corasick versions throw a deprecation warning let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags); - let mut build_cmd = runner.cargo_command(["build", "--example", "shootout-regex-dna", "--target", &runner.target_triple]); + let mut build_cmd = runner.cargo_command([ + "build", + "--example", + "shootout-regex-dna", + "--target", + &runner.target_triple, + ]); build_cmd.env("RUSTFLAGS", lint_rust_flags.clone()); spawn_and_wait(build_cmd); if runner.host_triple == runner.target_triple { - let mut run_cmd = runner.cargo_command(["run", "--example", "shootout-regex-dna", "--target", &runner.target_triple]); + let mut run_cmd = runner.cargo_command([ + "run", + "--example", + "shootout-regex-dna", + "--target", + &runner.target_triple, + ]); run_cmd.env("RUSTFLAGS", lint_rust_flags); - - let input = fs::read_to_string(PathBuf::from("examples/regexdna-input.txt")).unwrap(); + let input = + fs::read_to_string(PathBuf::from("examples/regexdna-input.txt")).unwrap(); let expected_path = PathBuf::from("examples/regexdna-output.txt"); let expected = fs::read_to_string(&expected_path).unwrap(); let output = spawn_and_wait_with_input(run_cmd, input); // Make sure `[codegen mono items] start` doesn't poison the diff - let output = output.lines() + let output = output + .lines() .filter(|line| !line.contains("codegen mono items")) .chain(Some("")) // This just adds the trailing newline .collect::>() .join("\r\n"); - let output_matches = expected.lines().eq(output.lines()); if !output_matches { let res_path = PathBuf::from("res.txt"); @@ -228,7 +352,6 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ } }); }), - TestCase::new("test.regex", &|runner| { runner.in_dir(["regex"], |runner| { runner.run_cargo(["clean"]); @@ -237,18 +360,27 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags); if runner.host_triple == runner.target_triple { - let mut run_cmd = runner.cargo_command(["test", "--tests", "--", "--exclude-should-panic", "--test-threads", "1", "-Zunstable-options", "-q"]); + let mut run_cmd = runner.cargo_command([ + "test", + "--tests", + "--", + "--exclude-should-panic", + "--test-threads", + "1", + "-Zunstable-options", + "-q", + ]); run_cmd.env("RUSTFLAGS", lint_rust_flags); spawn_and_wait(run_cmd); } else { eprintln!("Cross-Compiling: Not running tests"); - let mut build_cmd = runner.cargo_command(["build", "--tests", "--target", &runner.target_triple]); + let mut build_cmd = + runner.cargo_command(["build", "--tests", "--target", &runner.target_triple]); build_cmd.env("RUSTFLAGS", lint_rust_flags.clone()); spawn_and_wait(build_cmd); } }); }), - TestCase::new("test.portable-simd", &|runner| { runner.in_dir(["portable-simd"], |runner| { runner.run_cargo(["clean"]); @@ -261,8 +393,6 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ }), ]; - - pub(crate) fn run_tests( channel: &str, sysroot_kind: SysrootKind, @@ -316,8 +446,6 @@ pub(crate) fn run_tests( } } - - struct TestRunner { root_dir: PathBuf, out_dir: PathBuf, @@ -348,7 +476,7 @@ impl TestRunner { // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu. rust_flags = format!("-Clinker=aarch64-linux-gnu-gcc{}", rust_flags); run_wrapper = vec!["qemu-aarch64", "-L", "/usr/aarch64-linux-gnu"]; - }, + } "x86_64-pc-windows-gnu" => { // We are cross-compiling for Windows. Run tests in wine. run_wrapper = vec!["wine"]; diff --git a/build_system/utils.rs b/build_system/utils.rs index 2d2778d2fc0..3282778e254 100644 --- a/build_system/utils.rs +++ b/build_system/utils.rs @@ -1,7 +1,7 @@ use std::fs; +use std::io::Write; use std::path::Path; use std::process::{self, Command, Stdio}; -use std::io::Write; #[track_caller] pub(crate) fn try_hard_link(src: impl AsRef, dst: impl AsRef) { -- cgit 1.4.1-3-g733a5 From e26285603ca8b83b9d06e56f74e10e3d410553ff Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Sun, 31 Jul 2022 20:31:53 +0800 Subject: add test for earlier drop despite extend lifetime --- src/test/ui/let-else/let-else-temporary-lifetime.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/test/ui/let-else/let-else-temporary-lifetime.rs b/src/test/ui/let-else/let-else-temporary-lifetime.rs index 9c86901b97f..07fcc16e7bb 100644 --- a/src/test/ui/let-else/let-else-temporary-lifetime.rs +++ b/src/test/ui/let-else/let-else-temporary-lifetime.rs @@ -74,6 +74,17 @@ fn main() { }; } } + { + fn must_pass() { + let rc = Rc::new(()); + let &None = &Some(Rc::clone(&rc)) else { + Rc::try_unwrap(rc).unwrap(); + return; + }; + unreachable!(); + } + must_pass(); + } { // test let-else drops temps before else block // NOTE: this test has to be the last block in the `main` -- cgit 1.4.1-3-g733a5 From 8467a7b33ebdb0c8641e80c9c36bb098a93a7547 Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Sun, 31 Jul 2022 20:37:30 +0800 Subject: provide a clearer explanation of scope breaking --- compiler/rustc_mir_build/src/build/block.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index c52a7b187d5..280b6aad12c 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -84,8 +84,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mut let_scope_stack = Vec::with_capacity(8); let outer_source_scope = this.source_scope; let outer_in_scope_unsafe = this.in_scope_unsafe; - // This scope information is kept for breaking out of the current block in case + // This scope information is kept for breaking out of the parent remainder scope in case // one let-else pattern matching fails. + // By doing so, we can be sure that even temporaries that receive extended lifetime + // assignments are dropped, too. let mut last_remainder_scope = region_scope; this.update_source_scope_for_safety_mode(span, safety_mode); -- cgit 1.4.1-3-g733a5 From 04a7fefb20629af52d00018ac7013257eb661273 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 31 Jul 2022 22:00:53 +0300 Subject: linker: Update some outdated comments --- compiler/rustc_codegen_ssa/src/back/link.rs | 24 ++++++++++++------------ compiler/rustc_codegen_ssa/src/back/metadata.rs | 12 ++++++------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 13a7b6be947..8cd2ba54864 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1947,7 +1947,6 @@ fn linker_with_args<'a>( // Upstream rust libraries are not supposed to depend on our local native // libraries as that would violate the structure of the DAG, in that // scenario they are required to link to them as well in a shared fashion. - // (The current implementation still doesn't prevent it though, see the FIXME below.) // // Note that upstream rust libraries may contain native dependencies as // well, but they also can't depend on what we just started to add to the @@ -1968,15 +1967,16 @@ fn linker_with_args<'a>( // and move this option back to the top. cmd.add_as_needed(); - // FIXME: Move this below to other native libraries - // (or alternatively link all native libraries after their respective crates). - // This change is somewhat breaking in practice due to local static libraries being linked - // as whole-archive (#85144), so removing whole-archive may be a pre-requisite. + // Local native libraries of all kinds. + // + // If `-Zlink-native-libraries=false` is set, then the assumption is that an + // external build system already has the native dependencies defined, and it + // will provide them to the linker itself. if sess.opts.unstable_opts.link_native_libraries { add_local_native_libraries(cmd, sess, codegen_results); } - // Upstream rust libraries and their non-bundled static libraries + // Upstream rust libraries and their (possibly bundled) static native libraries. add_upstream_rust_crates( cmd, sess, @@ -1986,11 +1986,11 @@ fn linker_with_args<'a>( tmpdir, ); - // Upstream dynamic native libraries linked with `#[link]` attributes at and `-l` - // command line options. - // If -Zlink-native-libraries=false is set, then the assumption is that an - // external build system already has the native dependencies defined, and it - // will provide them to the linker itself. + // Dynamic native libraries from upstream crates. + // + // FIXME: Merge this to `add_upstream_rust_crates` so that all native libraries are linked + // together with their respective upstream crates, and in their originally specified order. + // This may be slightly breaking due to our use of `--as-needed` and needs a crater run. if sess.opts.unstable_opts.link_native_libraries { add_upstream_native_libraries(cmd, sess, codegen_results); } @@ -2401,7 +2401,7 @@ fn add_upstream_rust_crates<'a>( // or is an rlib already included via some other dylib crate, the symbols from // native libs will have already been included in that dylib. // - // If -Zlink-native-libraries=false is set, then the assumption is that an + // If `-Zlink-native-libraries=false` is set, then the assumption is that an // external build system already has the native dependencies defined, and it // will provide them to the linker itself. if sess.opts.unstable_opts.link_native_libraries { diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 0302c28815a..b92e146bee2 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -187,12 +187,12 @@ pub enum MetadataPosition { Last, } -// For rlibs we "pack" rustc metadata into a dummy object file. When rustc -// creates a dylib crate type it will pass `--whole-archive` (or the -// platform equivalent) to include all object files from an rlib into the -// final dylib itself. This causes linkers to iterate and try to include all -// files located in an archive, so if metadata is stored in an archive then -// it needs to be of a form that the linker will be able to process. +// For rlibs we "pack" rustc metadata into a dummy object file. +// +// Historically it was needed because rustc linked rlibs as whole-archive in some cases. +// In that case linkers try to include all files located in an archive, so if metadata is stored +// in an archive then it needs to be of a form that the linker is able to process. +// Now it's not clear whether metadata still needs to be wrapped into an object file or not. // // Note, though, that we don't actually want this metadata to show up in any // final output of the compiler. Instead this is purely for rustc's own -- cgit 1.4.1-3-g733a5 From 46fa744e6914bb4f09bc250f059e1879b65a7160 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Mon, 1 Aug 2022 09:49:54 +0100 Subject: Disable JIT on windows --- build_system/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_system/tests.rs b/build_system/tests.rs index 3f225b4efa2..dc83b10958e 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -465,7 +465,7 @@ impl TestRunner { out_dir.push("out"); let is_native = host_triple == target_triple; - let jit_supported = target_triple.contains("x86_64") && is_native; + let jit_supported = target_triple.contains("x86_64") && is_native && !host_triple.contains("windows"); let mut rust_flags = env::var("RUSTFLAGS").ok().unwrap_or("".to_string()); let mut run_wrapper = Vec::new(); -- cgit 1.4.1-3-g733a5 From 8f5330e28c0f694958044752aaea75fa5aeaa211 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Mon, 1 Aug 2022 09:57:43 +0100 Subject: Fix mini_core printf linking on windows Link against legacy_stdio_definitions on windows which provides printf as a linkable symbol. --- example/mini_core.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index 8b6042a3d66..f0e85ca478e 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -575,11 +575,19 @@ pub mod intrinsics { } pub mod libc { + // With the new Universal CRT, msvc has switched to all the printf functions being inline wrapper + // functions. legacy_stdio_definitions.lib which provides the printf wrapper functions as normal + // symbols to link against. + #[cfg_attr(unix, link(name = "c"))] + #[cfg_attr(target_env="msvc", link(name="legacy_stdio_definitions"))] + extern "C" { + pub fn printf(format: *const i8, ...) -> i32; + } + #[cfg_attr(unix, link(name = "c"))] #[cfg_attr(target_env = "msvc", link(name = "msvcrt"))] extern "C" { pub fn puts(s: *const i8) -> i32; - pub fn printf(format: *const i8, ...) -> i32; pub fn malloc(size: usize) -> *mut u8; pub fn free(ptr: *mut u8); pub fn memcpy(dst: *mut u8, src: *const u8, size: usize); -- cgit 1.4.1-3-g733a5 From e0fab632f1bd7473a08d4bb682f1bcc329efe01f Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Mon, 1 Aug 2022 11:38:56 +0100 Subject: Add windows support to mini_core tests --- example/mini_core.rs | 2 +- example/mini_core_hello_world.rs | 98 ++++++++++++++++++++++++++++++++++------ 2 files changed, 85 insertions(+), 15 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index f0e85ca478e..42f8aa50ba1 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -535,7 +535,7 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { } #[lang = "box_free"] -unsafe fn box_free(ptr: Unique, alloc: ()) { +unsafe fn box_free(ptr: Unique, _alloc: ()) { libc::free(ptr.pointer.0 as *mut u8); } diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index aa1f239bae2..412320997d5 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -139,7 +139,7 @@ pub struct bool_11 { field10: bool, } -extern "C" fn bool_struct_in_11(arg0: bool_11) {} +extern "C" fn bool_struct_in_11(_arg0: bool_11) {} #[allow(unreachable_code)] // FIXME false positive fn main() { @@ -375,6 +375,7 @@ struct pthread_attr_t { } #[link(name = "pthread")] +#[cfg(not(target_env="msvc"))] extern "C" { fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int; @@ -391,6 +392,86 @@ extern "C" { ) -> c_int; } +type DWORD = u32; +type LPDWORD = *mut u32; + +type LPVOID = *mut c_void; +type HANDLE = *mut c_void; + +#[link(name = "msvcrt")] +#[cfg(target_env="msvc")] +extern "C" { + fn WaitForSingleObject( + hHandle: LPVOID, + dwMilliseconds: DWORD + ) -> DWORD; + + fn CreateThread( + lpThreadAttributes: LPVOID, // Technically LPSECURITY_ATTRIBUTES, but we don't use it anyway + dwStackSize: usize, + lpStartAddress: extern "C" fn(_: *mut c_void) -> *mut c_void, + lpParameter: LPVOID, + dwCreationFlags: DWORD, + lpThreadId: LPDWORD + ) -> HANDLE; +} + +enum Thread { + Windows(HANDLE), + Pthread(pthread_t) +} + +impl Thread { + unsafe fn create(f: extern "C" fn(_: *mut c_void) -> *mut c_void) -> Self { + #[cfg(not(target_env="msvc"))] + { + let mut attr: pthread_attr_t = zeroed(); + let mut thread: pthread_t = 0; + + if pthread_attr_init(&mut attr) != 0 { + assert!(false); + } + + if pthread_create(&mut thread, &attr, f, 0 as *mut c_void) != 0 { + assert!(false); + } + + Thread::Pthread(thread) + } + + #[cfg(target_env="msvc")] + { + let handle = CreateThread(0 as *mut c_void, 0, f, 0 as *mut c_void, 0, 0 as *mut u32); + + if (handle as u64) == 0 { + assert!(false); + } + + Thread::Windows(handle) + } + } + + + unsafe fn join(self) { + match self { + #[cfg(not(target_env="msvc"))] + Thread::Pthread(thread) => { + let mut res = 0 as *mut c_void; + pthread_join(thread, &mut res); + } + #[cfg(target_env="msvc")] + Thread::Windows(handle) => { + let wait_time = 5000; // in milliseconds + assert!(WaitForSingleObject(handle, wait_time) == 0); + } + _ => assert!(false), + } + } +} + + + + #[thread_local] #[cfg(not(jit))] static mut TLS: u8 = 42; @@ -404,21 +485,10 @@ extern "C" fn mutate_tls(_: *mut c_void) -> *mut c_void { #[cfg(not(jit))] fn test_tls() { unsafe { - let mut attr: pthread_attr_t = zeroed(); - let mut thread: pthread_t = 0; - assert_eq!(TLS, 42); - if pthread_attr_init(&mut attr) != 0 { - assert!(false); - } - - if pthread_create(&mut thread, &attr, mutate_tls, 0 as *mut c_void) != 0 { - assert!(false); - } - - let mut res = 0 as *mut c_void; - pthread_join(thread, &mut res); + let thread = Thread::create(mutate_tls); + thread.join(); // TLS of main thread must not have been changed by the other thread. assert_eq!(TLS, 42); -- cgit 1.4.1-3-g733a5 From c9bb51961cf9b124c974f61ec4d0da59e4459c0b Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Mon, 1 Aug 2022 19:41:08 +0100 Subject: Misc Cleanups --- example/mini_core_hello_world.rs | 49 ++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 412320997d5..7e9cbe1bba5 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -375,7 +375,7 @@ struct pthread_attr_t { } #[link(name = "pthread")] -#[cfg(not(target_env="msvc"))] +#[cfg(unix)] extern "C" { fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int; @@ -399,14 +399,14 @@ type LPVOID = *mut c_void; type HANDLE = *mut c_void; #[link(name = "msvcrt")] -#[cfg(target_env="msvc")] +#[cfg(windows)] extern "C" { fn WaitForSingleObject( hHandle: LPVOID, dwMilliseconds: DWORD ) -> DWORD; - fn CreateThread( + fn CreateThread( lpThreadAttributes: LPVOID, // Technically LPSECURITY_ATTRIBUTES, but we don't use it anyway dwStackSize: usize, lpStartAddress: extern "C" fn(_: *mut c_void) -> *mut c_void, @@ -416,14 +416,16 @@ extern "C" { ) -> HANDLE; } -enum Thread { - Windows(HANDLE), - Pthread(pthread_t) +struct Thread { + #[cfg(windows)] + handle: HANDLE, + #[cfg(unix)] + handle: pthread_t, } impl Thread { unsafe fn create(f: extern "C" fn(_: *mut c_void) -> *mut c_void) -> Self { - #[cfg(not(target_env="msvc"))] + #[cfg(unix)] { let mut attr: pthread_attr_t = zeroed(); let mut thread: pthread_t = 0; @@ -436,10 +438,12 @@ impl Thread { assert!(false); } - Thread::Pthread(thread) + Thread { + handle: thread, + } } - #[cfg(target_env="msvc")] + #[cfg(windows)] { let handle = CreateThread(0 as *mut c_void, 0, f, 0 as *mut c_void, 0, 0 as *mut u32); @@ -447,24 +451,25 @@ impl Thread { assert!(false); } - Thread::Windows(handle) + Thread { + handle, + } } } unsafe fn join(self) { - match self { - #[cfg(not(target_env="msvc"))] - Thread::Pthread(thread) => { - let mut res = 0 as *mut c_void; - pthread_join(thread, &mut res); - } - #[cfg(target_env="msvc")] - Thread::Windows(handle) => { - let wait_time = 5000; // in milliseconds - assert!(WaitForSingleObject(handle, wait_time) == 0); - } - _ => assert!(false), + #[cfg(unix)] + { + let mut res = 0 as *mut c_void; + pthread_join(self.handle, &mut res); + } + + #[cfg(windows)] + { + // The INFINITE macro is used to signal operations that do not timeout. + let infinite = 0xffffffff; + assert!(WaitForSingleObject(self.handle, infinite) == 0); } } } -- cgit 1.4.1-3-g733a5 From 97c963d0812c347eaa02b7194f96c4bc01ab9698 Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Tue, 2 Aug 2022 22:22:16 +0200 Subject: make slice::{split_at,split_at_unchecked} const functions --- library/core/src/lib.rs | 1 + library/core/src/slice/mod.rs | 13 +++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 24742bb49b9..3a03edfb646 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -137,6 +137,7 @@ #![feature(const_size_of_val)] #![feature(const_slice_from_raw_parts_mut)] #![feature(const_slice_ptr_len)] +#![feature(const_slice_split_at_not_mut)] #![feature(const_str_from_utf8_unchecked_mut)] #![feature(const_swap)] #![feature(const_trait_impl)] diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index e6ca6ef8267..2336ad9cae3 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -1538,13 +1538,14 @@ impl [T] { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_slice_split_at_not_mut", issue = "none")] #[inline] #[track_caller] #[must_use] - pub fn split_at(&self, mid: usize) -> (&[T], &[T]) { + pub const fn split_at(&self, mid: usize) -> (&[T], &[T]) { assert!(mid <= self.len()); // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which - // fulfills the requirements of `from_raw_parts_mut`. + // fulfills the requirements of `split_at_unchecked`. unsafe { self.split_at_unchecked(mid) } } @@ -1623,11 +1624,15 @@ impl [T] { /// } /// ``` #[unstable(feature = "slice_split_at_unchecked", reason = "new API", issue = "76014")] + #[rustc_const_unstable(feature = "const_slice_split_at_not_mut", issue = "none")] #[inline] #[must_use] - pub unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T]) { + pub const unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T]) { + let len = self.len(); + let ptr = self.as_ptr(); + // SAFETY: Caller has to check that `0 <= mid <= self.len()` - unsafe { (self.get_unchecked(..mid), self.get_unchecked(mid..)) } + unsafe { (from_raw_parts(ptr, mid), from_raw_parts(ptr.add(mid), len - mid)) } } /// Divides one mutable slice into two at an index, without doing bounds checking. -- cgit 1.4.1-3-g733a5 From ee3fc9dff8f2cff217883cd4a6f979677a1263f9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 2 Aug 2022 15:47:14 -0400 Subject: never consider unsafe blocks unused if they would be required with unsafe_op_in_unsafe_fn --- compiler/rustc_errors/src/diagnostic_builder.rs | 2 +- compiler/rustc_mir_build/src/check_unsafety.rs | 8 +- compiler/rustc_mir_transform/src/check_unsafety.rs | 37 +- src/test/ui/span/lint-unused-unsafe-thir.rs | 4 +- src/test/ui/span/lint-unused-unsafe-thir.stderr | 18 +- src/test/ui/span/lint-unused-unsafe.mir.stderr | 548 +++------------------ src/test/ui/span/lint-unused-unsafe.rs | 74 +-- .../rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr | 38 +- .../ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs | 2 - .../rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr | 24 +- 10 files changed, 124 insertions(+), 631 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 9e68ee282e6..04159bff4ff 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -566,7 +566,7 @@ impl Drop for DiagnosticBuilderInner<'_> { ), )); handler.emit_diagnostic(&mut self.diagnostic); - panic!(); + panic!("error was constructed but not emitted"); } } // `.emit()` was previously called, or maybe we're during `.cancel()`. diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 864caf0ba31..e3157a43001 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -75,10 +75,10 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { match self.safety_context { SafetyContext::BuiltinUnsafeBlock => {} SafetyContext::UnsafeBlock { ref mut used, .. } => { - if !self.body_unsafety.is_unsafe() || !unsafe_op_in_unsafe_fn_allowed { - // Mark this block as useful - *used = true; - } + // Mark this block as useful (even inside `unsafe fn`, where it is technically + // redundant -- but we want to eventually enable `unsafe_op_in_unsafe_fn` by + // default which will require those blocks). + *used = true; } SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {} SafetyContext::UnsafeFn => { diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index d564f480166..9ea87245d03 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -5,9 +5,9 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::hir_id::HirId; use rustc_hir::intravisit; use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; +use rustc_middle::mir::*; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt}; -use rustc_middle::{lint, mir::*}; use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; use rustc_session::lint::Level; @@ -259,7 +259,7 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> { violations: impl IntoIterator, new_used_unsafe_blocks: impl IntoIterator, ) { - use UsedUnsafeBlockData::{AllAllowedInUnsafeFn, SomeDisallowedInUnsafeFn}; + use UsedUnsafeBlockData::*; let update_entry = |this: &mut Self, hir_id, new_usage| { match this.used_unsafe_blocks.entry(hir_id) { @@ -299,15 +299,11 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> { } }), Safety::BuiltinUnsafe => {} - Safety::ExplicitUnsafe(hir_id) => violations.into_iter().for_each(|violation| { + Safety::ExplicitUnsafe(hir_id) => violations.into_iter().for_each(|_violation| { update_entry( self, hir_id, - match self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, violation.lint_root).0 - { - Level::Allow => AllAllowedInUnsafeFn(violation.lint_root), - _ => SomeDisallowedInUnsafeFn, - }, + SomeDisallowedInUnsafeFn, ) }), }; @@ -522,6 +518,11 @@ fn unsafety_check_result<'tcx>( } fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) { + if matches!(kind, UnusedUnsafe::InUnsafeFn(..)) { + // We do *not* warn here, these unsafe blocks are actually required when + // `unsafe_op_in_unsafe_fn` is warn or higher. + return; + } let span = tcx.sess.source_map().guess_head_span(tcx.hir().span(id)); tcx.struct_span_lint_hir(UNUSED_UNSAFE, id, span, |lint| { let msg = "unnecessary `unsafe` block"; @@ -535,25 +536,7 @@ fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) { "because it's nested under this `unsafe` block", ); } - UnusedUnsafe::InUnsafeFn(id, usage_lint_root) => { - db.span_label( - tcx.sess.source_map().guess_head_span(tcx.hir().span(id)), - "because it's nested under this `unsafe` fn", - ) - .note( - "this `unsafe` block does contain unsafe operations, \ - but those are already allowed in an `unsafe fn`", - ); - let (level, source) = - tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, usage_lint_root); - assert_eq!(level, Level::Allow); - lint::explain_lint_level_source( - UNSAFE_OP_IN_UNSAFE_FN, - Level::Allow, - source, - &mut db, - ); - } + UnusedUnsafe::InUnsafeFn(_id, _usage_lint_root) => unreachable!(), } db.emit(); diff --git a/src/test/ui/span/lint-unused-unsafe-thir.rs b/src/test/ui/span/lint-unused-unsafe-thir.rs index 95a537ed282..adb72c26bba 100644 --- a/src/test/ui/span/lint-unused-unsafe-thir.rs +++ b/src/test/ui/span/lint-unused-unsafe-thir.rs @@ -22,7 +22,7 @@ fn bad1() { unsafe {} } //~ ERROR: unnecessary `unsafe` block fn bad2() { unsafe { bad1() } } //~ ERROR: unnecessary `unsafe` block unsafe fn bad3() { unsafe {} } //~ ERROR: unnecessary `unsafe` block fn bad4() { unsafe { callback(||{}) } } //~ ERROR: unnecessary `unsafe` block -unsafe fn bad5() { unsafe { unsf() } } //~ ERROR: unnecessary `unsafe` block +unsafe fn bad5() { unsafe { unsf() } } fn bad6() { unsafe { // don't put the warning here unsafe { //~ ERROR: unnecessary `unsafe` block @@ -31,7 +31,7 @@ fn bad6() { } } unsafe fn bad7() { - unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { unsafe { //~ ERROR: unnecessary `unsafe` block unsf() } diff --git a/src/test/ui/span/lint-unused-unsafe-thir.stderr b/src/test/ui/span/lint-unused-unsafe-thir.stderr index 6654910c5cd..3bcbb759775 100644 --- a/src/test/ui/span/lint-unused-unsafe-thir.stderr +++ b/src/test/ui/span/lint-unused-unsafe-thir.stderr @@ -30,14 +30,6 @@ error: unnecessary `unsafe` block LL | fn bad4() { unsafe { callback(||{}) } } | ^^^^^^ unnecessary `unsafe` block -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe-thir.rs:25:20 - | -LL | unsafe fn bad5() { unsafe { unsf() } } - | ---------------- ^^^^^^ unnecessary `unsafe` block - | | - | because it's nested under this `unsafe` fn - error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe-thir.rs:28:9 | @@ -54,13 +46,5 @@ LL | unsafe { LL | unsafe { | ^^^^^^ unnecessary `unsafe` block -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe-thir.rs:34:5 - | -LL | unsafe fn bad7() { - | ---------------- because it's nested under this `unsafe` fn -LL | unsafe { - | ^^^^^^ unnecessary `unsafe` block - -error: aborting due to 8 previous errors +error: aborting due to 6 previous errors diff --git a/src/test/ui/span/lint-unused-unsafe.mir.stderr b/src/test/ui/span/lint-unused-unsafe.mir.stderr index 850550a1d8f..d8412908c73 100644 --- a/src/test/ui/span/lint-unused-unsafe.mir.stderr +++ b/src/test/ui/span/lint-unused-unsafe.mir.stderr @@ -28,17 +28,6 @@ error: unnecessary `unsafe` block LL | fn bad4() { unsafe { callback(||{}) } } | ^^^^^^ unnecessary `unsafe` block -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:30:20 - | -LL | unsafe fn bad5() { unsafe { unsf() } } - | ---------------- ^^^^^^ unnecessary `unsafe` block - | | - | because it's nested under this `unsafe` fn - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` - = note: `#[allow(unsafe_op_in_unsafe_fn)]` on by default - error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:32:5 | @@ -51,17 +40,6 @@ error: unnecessary `unsafe` block LL | unsafe { | ^^^^^^ unnecessary `unsafe` block -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:40:9 - | -LL | unsafe fn bad7() { - | ---------------- because it's nested under this `unsafe` fn -LL | unsafe { -LL | unsafe { - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` - error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:74:9 | @@ -272,91 +250,32 @@ error: unnecessary `unsafe` block LL | unsafe { | ^^^^^^ unnecessary `unsafe` block -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:197:13 - | -LL | unsafe fn granularity_2() { - | ------------------------- because it's nested under this `unsafe` fn -LL | unsafe { -LL | unsafe { unsf() } - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` -note: the lint level is defined here - --> $DIR/lint-unused-unsafe.rs:194:13 - | -LL | #[allow(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:198:13 - | -LL | unsafe fn granularity_2() { - | ------------------------- because it's nested under this `unsafe` fn -... -LL | unsafe { unsf() } - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` - -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:199:13 - | -LL | unsafe fn granularity_2() { - | ------------------------- because it's nested under this `unsafe` fn -... -LL | unsafe { unsf() } - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` - -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:205:9 - | -LL | unsafe fn top_level_used_2() { - | ---------------------------- because it's nested under this `unsafe` fn -LL | unsafe { - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` -note: the lint level is defined here - --> $DIR/lint-unused-unsafe.rs:203:13 - | -LL | #[allow(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ - error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:207:13 | -LL | unsafe fn top_level_used_2() { - | ---------------------------- because it's nested under this `unsafe` fn -... +LL | unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); LL | unsafe { unsf() } | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:208:13 | -LL | unsafe fn top_level_used_2() { - | ---------------------------- because it's nested under this `unsafe` fn +LL | unsafe { + | ------ because it's nested under this `unsafe` block ... LL | unsafe { unsf() } | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:209:13 | -LL | unsafe fn top_level_used_2() { - | ---------------------------- because it's nested under this `unsafe` fn +LL | unsafe { + | ------ because it's nested under this `unsafe` block ... LL | unsafe { unsf() } | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:220:17 @@ -398,19 +317,12 @@ LL | unsafe { | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:254:9 + --> $DIR/lint-unused-unsafe.rs:255:13 | -LL | unsafe fn granular_disallow_op_in_unsafe_fn_3() { - | ----------------------------------------------- because it's nested under this `unsafe` fn LL | unsafe { - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` -note: the lint level is defined here - --> $DIR/lint-unused-unsafe.rs:252:13 - | -LL | #[allow(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ + | ------ because it's nested under this `unsafe` block +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:268:13 @@ -630,91 +542,32 @@ error: unnecessary `unsafe` block LL | let _ = || unsafe { | ^^^^^^ unnecessary `unsafe` block -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:409:24 - | -LL | unsafe fn granularity_2() { - | ------------------------- because it's nested under this `unsafe` fn -LL | let _ = || unsafe { -LL | let _ = || unsafe { unsf() }; - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` -note: the lint level is defined here - --> $DIR/lint-unused-unsafe.rs:406:13 - | -LL | #[allow(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:410:24 - | -LL | unsafe fn granularity_2() { - | ------------------------- because it's nested under this `unsafe` fn -... -LL | let _ = || unsafe { unsf() }; - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` - -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:411:24 - | -LL | unsafe fn granularity_2() { - | ------------------------- because it's nested under this `unsafe` fn -... -LL | let _ = || unsafe { unsf() }; - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` - -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:417:20 - | -LL | unsafe fn top_level_used_2() { - | ---------------------------- because it's nested under this `unsafe` fn -LL | let _ = || unsafe { - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` -note: the lint level is defined here - --> $DIR/lint-unused-unsafe.rs:415:13 - | -LL | #[allow(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ - error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:419:24 | -LL | unsafe fn top_level_used_2() { - | ---------------------------- because it's nested under this `unsafe` fn -... +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); LL | let _ = || unsafe { unsf() }; | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:420:24 | -LL | unsafe fn top_level_used_2() { - | ---------------------------- because it's nested under this `unsafe` fn +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block ... LL | let _ = || unsafe { unsf() }; | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:421:24 | -LL | unsafe fn top_level_used_2() { - | ---------------------------- because it's nested under this `unsafe` fn +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block ... LL | let _ = || unsafe { unsf() }; | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:432:28 @@ -756,19 +609,12 @@ LL | let _ = || unsafe { | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:466:20 + --> $DIR/lint-unused-unsafe.rs:467:24 | -LL | unsafe fn granular_disallow_op_in_unsafe_fn_3() { - | ----------------------------------------------- because it's nested under this `unsafe` fn LL | let _ = || unsafe { - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` -note: the lint level is defined here - --> $DIR/lint-unused-unsafe.rs:464:13 - | -LL | #[allow(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:480:24 @@ -988,91 +834,32 @@ error: unnecessary `unsafe` block LL | let _ = || unsafe { | ^^^^^^ unnecessary `unsafe` block -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:622:24 - | -LL | unsafe fn granularity_2() { - | ------------------------- because it's nested under this `unsafe` fn -LL | let _ = || unsafe { -LL | let _ = || unsafe { let _ = || unsf(); }; - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` -note: the lint level is defined here - --> $DIR/lint-unused-unsafe.rs:619:13 - | -LL | #[allow(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:623:24 - | -LL | unsafe fn granularity_2() { - | ------------------------- because it's nested under this `unsafe` fn -... -LL | let _ = || unsafe { let _ = || unsf(); }; - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` - -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:624:24 - | -LL | unsafe fn granularity_2() { - | ------------------------- because it's nested under this `unsafe` fn -... -LL | let _ = || unsafe { let _ = || unsf(); }; - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` - -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:630:20 - | -LL | unsafe fn top_level_used_2() { - | ---------------------------- because it's nested under this `unsafe` fn -LL | let _ = || unsafe { - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` -note: the lint level is defined here - --> $DIR/lint-unused-unsafe.rs:628:13 - | -LL | #[allow(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ - error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:632:24 | -LL | unsafe fn top_level_used_2() { - | ---------------------------- because it's nested under this `unsafe` fn -... +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsf(); LL | let _ = || unsafe { let _ = || unsf(); }; | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:633:24 | -LL | unsafe fn top_level_used_2() { - | ---------------------------- because it's nested under this `unsafe` fn +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block ... LL | let _ = || unsafe { let _ = || unsf(); }; | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:634:24 | -LL | unsafe fn top_level_used_2() { - | ---------------------------- because it's nested under this `unsafe` fn +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block ... LL | let _ = || unsafe { let _ = || unsf(); }; | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:645:28 @@ -1114,19 +901,12 @@ LL | let _ = || unsafe { | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:679:20 + --> $DIR/lint-unused-unsafe.rs:680:24 | -LL | unsafe fn granular_disallow_op_in_unsafe_fn_3() { - | ----------------------------------------------- because it's nested under this `unsafe` fn LL | let _ = || unsafe { - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` -note: the lint level is defined here - --> $DIR/lint-unused-unsafe.rs:677:13 - | -LL | #[allow(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:693:24 @@ -1256,91 +1036,32 @@ error: unnecessary `unsafe` block LL | let _ = || unsafe { | ^^^^^^ unnecessary `unsafe` block -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:784:28 - | -LL | unsafe fn granularity_2() { - | ------------------------- because it's nested under this `unsafe` fn -LL | let _ = || unsafe { -LL | let _ = || unsafe { unsf() }; - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` -note: the lint level is defined here - --> $DIR/lint-unused-unsafe.rs:781:17 - | -LL | #[allow(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:785:28 - | -LL | unsafe fn granularity_2() { - | ------------------------- because it's nested under this `unsafe` fn -... -LL | let _ = || unsafe { unsf() }; - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` - -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:786:28 - | -LL | unsafe fn granularity_2() { - | ------------------------- because it's nested under this `unsafe` fn -... -LL | let _ = || unsafe { unsf() }; - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` - -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:792:24 - | -LL | unsafe fn top_level_used_2() { - | ---------------------------- because it's nested under this `unsafe` fn -LL | let _ = || unsafe { - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` -note: the lint level is defined here - --> $DIR/lint-unused-unsafe.rs:790:17 - | -LL | #[allow(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ - error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:794:28 | -LL | unsafe fn top_level_used_2() { - | ---------------------------- because it's nested under this `unsafe` fn -... +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); LL | let _ = || unsafe { unsf() }; | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:795:28 | -LL | unsafe fn top_level_used_2() { - | ---------------------------- because it's nested under this `unsafe` fn +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block ... LL | let _ = || unsafe { unsf() }; | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:796:28 | -LL | unsafe fn top_level_used_2() { - | ---------------------------- because it's nested under this `unsafe` fn +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block ... LL | let _ = || unsafe { unsf() }; | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:807:32 @@ -1382,19 +1103,12 @@ LL | let _ = || unsafe { | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:841:24 + --> $DIR/lint-unused-unsafe.rs:842:28 | -LL | unsafe fn granular_disallow_op_in_unsafe_fn_3() { - | ----------------------------------------------- because it's nested under this `unsafe` fn LL | let _ = || unsafe { - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` -note: the lint level is defined here - --> $DIR/lint-unused-unsafe.rs:839:17 - | -LL | #[allow(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:855:28 @@ -1524,91 +1238,32 @@ error: unnecessary `unsafe` block LL | let _ = || unsafe { | ^^^^^^ unnecessary `unsafe` block -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:942:28 - | -LL | unsafe fn granularity_2() { - | ------------------------- because it's nested under this `unsafe` fn -LL | let _ = || unsafe { -LL | let _ = || unsafe { unsf() }; - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` -note: the lint level is defined here - --> $DIR/lint-unused-unsafe.rs:939:17 - | -LL | #[allow(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:943:28 - | -LL | unsafe fn granularity_2() { - | ------------------------- because it's nested under this `unsafe` fn -... -LL | let _ = || unsafe { unsf() }; - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` - -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:944:28 - | -LL | unsafe fn granularity_2() { - | ------------------------- because it's nested under this `unsafe` fn -... -LL | let _ = || unsafe { unsf() }; - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` - -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:950:24 - | -LL | unsafe fn top_level_used_2() { - | ---------------------------- because it's nested under this `unsafe` fn -LL | let _ = || unsafe { - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` -note: the lint level is defined here - --> $DIR/lint-unused-unsafe.rs:948:17 - | -LL | #[allow(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ - error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:952:28 | -LL | unsafe fn top_level_used_2() { - | ---------------------------- because it's nested under this `unsafe` fn -... +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); LL | let _ = || unsafe { unsf() }; | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:953:28 | -LL | unsafe fn top_level_used_2() { - | ---------------------------- because it's nested under this `unsafe` fn +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block ... LL | let _ = || unsafe { unsf() }; | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:954:28 | -LL | unsafe fn top_level_used_2() { - | ---------------------------- because it's nested under this `unsafe` fn +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block ... LL | let _ = || unsafe { unsf() }; | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:965:32 @@ -1650,19 +1305,12 @@ LL | let _ = || unsafe { | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:999:24 + --> $DIR/lint-unused-unsafe.rs:1000:28 | -LL | unsafe fn granular_disallow_op_in_unsafe_fn_3() { - | ----------------------------------------------- because it's nested under this `unsafe` fn LL | let _ = || unsafe { - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` -note: the lint level is defined here - --> $DIR/lint-unused-unsafe.rs:997:17 - | -LL | #[allow(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:1013:28 @@ -1672,21 +1320,6 @@ LL | let _ = || unsafe { LL | let _ = || unsafe { | ^^^^^^ unnecessary `unsafe` block -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:1044:9 - | -LL | unsafe fn multiple_unsafe_op_in_unsafe_fn_allows() { - | -------------------------------------------------- because it's nested under this `unsafe` fn -LL | unsafe { - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` -note: the lint level is defined here - --> $DIR/lint-unused-unsafe.rs:1045:21 - | -LL | #[allow(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ - error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:1059:29 | @@ -1726,87 +1359,32 @@ error: unnecessary `unsafe` block LL | let _ = async { unsafe { | ^^^^^^ unnecessary `unsafe` block -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:1074:33 - | -LL | async unsafe fn async_blocks() { - | ------------------------------ because it's nested under this `unsafe` fn -... -LL | let _ = async { unsafe { let _ = async { unsf() }; }}; - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` -note: the lint level is defined here - --> $DIR/lint-unused-unsafe.rs:1071:17 - | -LL | #[allow(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:1075:33 - | -LL | async unsafe fn async_blocks() { - | ------------------------------ because it's nested under this `unsafe` fn -... -LL | let _ = async { unsafe { let _ = async { unsf() }; }}; - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` - -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:1076:33 - | -LL | async unsafe fn async_blocks() { - | ------------------------------ because it's nested under this `unsafe` fn -... -LL | let _ = async { unsafe { let _ = async { unsf() }; }}; - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` - -error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:1078:29 - | -LL | async unsafe fn async_blocks() { - | ------------------------------ because it's nested under this `unsafe` fn -... -LL | let _ = async { unsafe { - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` - error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:1080:33 | -LL | async unsafe fn async_blocks() { - | ------------------------------ because it's nested under this `unsafe` fn -... +LL | let _ = async { unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = async { unsf() }; LL | let _ = async { unsafe { let _ = async { unsf() }; }}; | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:1081:33 | -LL | async unsafe fn async_blocks() { - | ------------------------------ because it's nested under this `unsafe` fn +LL | let _ = async { unsafe { + | ------ because it's nested under this `unsafe` block ... LL | let _ = async { unsafe { let _ = async { unsf() }; }}; | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:1082:33 | -LL | async unsafe fn async_blocks() { - | ------------------------------ because it's nested under this `unsafe` fn +LL | let _ = async { unsafe { + | ------ because it's nested under this `unsafe` block ... LL | let _ = async { unsafe { let _ = async { unsf() }; }}; | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` error: unnecessary `unsafe` block --> $DIR/lint-unused-unsafe.rs:1092:22 @@ -1820,5 +1398,5 @@ error: unnecessary `unsafe` block LL | let _x: [(); unsafe { unsafe { size() } }] = []; | ^^^^^^ unnecessary `unsafe` block -error: aborting due to 201 previous errors +error: aborting due to 174 previous errors diff --git a/src/test/ui/span/lint-unused-unsafe.rs b/src/test/ui/span/lint-unused-unsafe.rs index f8d1dff3572..5d042768be0 100644 --- a/src/test/ui/span/lint-unused-unsafe.rs +++ b/src/test/ui/span/lint-unused-unsafe.rs @@ -27,7 +27,7 @@ fn bad1() { unsafe {} } //~ ERROR: unnecessary `unsafe` block fn bad2() { unsafe { bad1() } } //~ ERROR: unnecessary `unsafe` block unsafe fn bad3() { unsafe {} } //~ ERROR: unnecessary `unsafe` block fn bad4() { unsafe { callback(||{}) } } //~ ERROR: unnecessary `unsafe` block -unsafe fn bad5() { unsafe { unsf() } } //~ ERROR: unnecessary `unsafe` block +unsafe fn bad5() { unsafe { unsf() } } fn bad6() { unsafe { //~ ERROR: unnecessary `unsafe` block unsafe { // don't put the warning here @@ -37,7 +37,7 @@ fn bad6() { } unsafe fn bad7() { unsafe { //~ ERROR: unnecessary `unsafe` block - unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } } @@ -194,15 +194,15 @@ mod additional_tests { #[allow(unsafe_op_in_unsafe_fn)] unsafe fn granularity_2() { unsafe { //~ ERROR: unnecessary `unsafe` block - unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block - unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block - unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } + unsafe { unsf() } + unsafe { unsf() } } } #[allow(unsafe_op_in_unsafe_fn)] unsafe fn top_level_used_2() { - unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { unsf(); unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block @@ -251,8 +251,8 @@ mod additional_tests { #[allow(unsafe_op_in_unsafe_fn)] unsafe fn granular_disallow_op_in_unsafe_fn_3() { - unsafe { //~ ERROR: unnecessary `unsafe` block - unsafe { + unsafe { + unsafe { //~ ERROR: unnecessary `unsafe` block #[deny(unsafe_op_in_unsafe_fn)] { unsf(); @@ -406,15 +406,15 @@ mod additional_tests_closures { #[allow(unsafe_op_in_unsafe_fn)] unsafe fn granularity_2() { let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block - let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block - let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block - let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; }; } #[allow(unsafe_op_in_unsafe_fn)] unsafe fn top_level_used_2() { - let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf(); let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block @@ -463,8 +463,8 @@ mod additional_tests_closures { #[allow(unsafe_op_in_unsafe_fn)] unsafe fn granular_disallow_op_in_unsafe_fn_3() { - let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block - let _ = || unsafe { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block #[deny(unsafe_op_in_unsafe_fn)] { unsf(); @@ -619,15 +619,15 @@ mod additional_tests_even_more_closures { #[allow(unsafe_op_in_unsafe_fn)] unsafe fn granularity_2() { let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block - let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block - let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block - let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; + let _ = || unsafe { let _ = || unsf(); }; + let _ = || unsafe { let _ = || unsf(); }; }; } #[allow(unsafe_op_in_unsafe_fn)] unsafe fn top_level_used_2() { - let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block @@ -676,8 +676,8 @@ mod additional_tests_even_more_closures { #[allow(unsafe_op_in_unsafe_fn)] unsafe fn granular_disallow_op_in_unsafe_fn_3() { - let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block - let _ = || unsafe { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block #[deny(unsafe_op_in_unsafe_fn)] { let _ = || unsf(); @@ -781,15 +781,15 @@ mod item_likes { #[allow(unsafe_op_in_unsafe_fn)] unsafe fn granularity_2() { let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block - let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block - let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block - let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; }; } #[allow(unsafe_op_in_unsafe_fn)] unsafe fn top_level_used_2() { - let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf(); let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block @@ -838,8 +838,8 @@ mod item_likes { #[allow(unsafe_op_in_unsafe_fn)] unsafe fn granular_disallow_op_in_unsafe_fn_3() { - let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block - let _ = || unsafe { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block #[deny(unsafe_op_in_unsafe_fn)] { unsf(); @@ -939,15 +939,15 @@ mod item_likes { #[allow(unsafe_op_in_unsafe_fn)] unsafe fn granularity_2() { let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block - let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block - let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block - let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; }; } #[allow(unsafe_op_in_unsafe_fn)] unsafe fn top_level_used_2() { - let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf(); let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block @@ -996,8 +996,8 @@ mod item_likes { #[allow(unsafe_op_in_unsafe_fn)] unsafe fn granular_disallow_op_in_unsafe_fn_3() { - let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block - let _ = || unsafe { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block #[deny(unsafe_op_in_unsafe_fn)] { unsf(); @@ -1041,7 +1041,7 @@ mod additional_tests_extra { #[warn(unsafe_op_in_unsafe_fn)] unsafe fn multiple_unsafe_op_in_unsafe_fn_allows() { - unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { #[allow(unsafe_op_in_unsafe_fn)] { unsf(); @@ -1071,11 +1071,11 @@ mod additional_tests_extra { #[allow(unsafe_op_in_unsafe_fn)] { let _ = async { unsafe { //~ ERROR: unnecessary `unsafe` block - let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block - let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block - let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block + let _ = async { unsafe { let _ = async { unsf() }; }}; + let _ = async { unsafe { let _ = async { unsf() }; }}; + let _ = async { unsafe { let _ = async { unsf() }; }}; }}; - let _ = async { unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = async { unsafe { let _ = async { unsf() }; let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block diff --git a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr index fd58e1b1ebe..b968174dd2d 100644 --- a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr +++ b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr @@ -81,40 +81,8 @@ error: unnecessary `unsafe` block LL | unsafe { unsafe { unsf() } } | ^^^^^^ unnecessary `unsafe` block -error: unnecessary `unsafe` block - --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:60:5 - | -LL | unsafe fn allow_level() { - | ----------------------- because it's nested under this `unsafe` fn -... -LL | unsafe { unsf() } - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` -note: the lint level is defined here - --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:53:9 - | -LL | #[allow(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: unnecessary `unsafe` block - --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:72:9 - | -LL | unsafe fn nested_allow_level() { - | ------------------------------ because it's nested under this `unsafe` fn -... -LL | unsafe { unsf() } - | ^^^^^^ unnecessary `unsafe` block - | - = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` -note: the lint level is defined here - --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:65:13 - | -LL | #[allow(unsafe_op_in_unsafe_fn)] - | ^^^^^^^^^^^^^^^^^^^^^^ - error[E0133]: call to unsafe function is unsafe and requires unsafe block - --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:78:5 + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:76:5 | LL | unsf(); | ^^^^^^ call to unsafe function @@ -122,13 +90,13 @@ LL | unsf(); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:83:9 + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:81:9 | LL | unsf(); | ^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to 13 previous errors +error: aborting due to 11 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs index 30b07234034..db1e916a36c 100644 --- a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs +++ b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs @@ -58,7 +58,6 @@ unsafe fn allow_level() { VOID = (); unsafe { unsf() } - //~^ ERROR unnecessary `unsafe` block } unsafe fn nested_allow_level() { @@ -70,7 +69,6 @@ unsafe fn nested_allow_level() { VOID = (); unsafe { unsf() } - //~^ ERROR unnecessary `unsafe` block } } diff --git a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr index 2ba6a72930d..e365293657e 100644 --- a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr +++ b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr @@ -83,26 +83,8 @@ LL | unsafe { unsafe { unsf() } } | | | because it's nested under this `unsafe` block -error: unnecessary `unsafe` block - --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:60:5 - | -LL | unsafe fn allow_level() { - | ----------------------- because it's nested under this `unsafe` fn -... -LL | unsafe { unsf() } - | ^^^^^^ unnecessary `unsafe` block - -error: unnecessary `unsafe` block - --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:72:9 - | -LL | unsafe fn nested_allow_level() { - | ------------------------------ because it's nested under this `unsafe` fn -... -LL | unsafe { unsf() } - | ^^^^^^ unnecessary `unsafe` block - error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block - --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:78:5 + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:76:5 | LL | unsf(); | ^^^^^^ call to unsafe function @@ -110,13 +92,13 @@ LL | unsf(); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe function or block - --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:83:9 + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:81:9 | LL | unsf(); | ^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to 13 previous errors +error: aborting due to 11 previous errors For more information about this error, try `rustc --explain E0133`. -- cgit 1.4.1-3-g733a5 From 3e44ca95dd844863eeb9bba44209e43d2afb81a4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 2 Aug 2022 17:04:52 -0400 Subject: remove some unused code and types --- compiler/rustc_middle/src/mir/query.rs | 22 +------- compiler/rustc_mir_transform/src/check_unsafety.rs | 64 +++++----------------- 2 files changed, 17 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index dd9f8795f94..594c14a642d 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -2,7 +2,7 @@ use crate::mir::{Body, ConstantKind, Promoted}; use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt}; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::vec_map::VecMap; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; @@ -115,21 +115,6 @@ pub enum UnusedUnsafe { /// `unsafe` block nested under another (used) `unsafe` block /// > ``… because it's nested under this `unsafe` block`` InUnsafeBlock(hir::HirId), - /// `unsafe` block nested under `unsafe fn` - /// > ``… because it's nested under this `unsafe fn` `` - /// - /// the second HirId here indicates the first usage of the `unsafe` block, - /// which allows retrieval of the LintLevelSource for why that operation would - /// have been permitted without the block - InUnsafeFn(hir::HirId, hir::HirId), -} - -#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] -pub enum UsedUnsafeBlockData { - SomeDisallowedInUnsafeFn, - // the HirId here indicates the first usage of the `unsafe` block - // (i.e. the one that's first encountered in the MIR traversal of the unsafety check) - AllAllowedInUnsafeFn(hir::HirId), } #[derive(TyEncodable, TyDecodable, HashStable, Debug)] @@ -138,10 +123,7 @@ pub struct UnsafetyCheckResult { pub violations: Vec, /// Used `unsafe` blocks in this function. This is used for the "unused_unsafe" lint. - /// - /// The keys are the used `unsafe` blocks, the UnusedUnsafeKind indicates whether - /// or not any of the usages happen at a place that doesn't allow `unsafe_op_in_unsafe_fn`. - pub used_unsafe_blocks: FxHashMap, + pub used_unsafe_blocks: FxHashSet, /// This is `Some` iff the item is not a closure. pub unused_unsafes: Option>, diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index 9ea87245d03..a9eb60c7a15 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -1,4 +1,4 @@ -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -11,7 +11,6 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; use rustc_session::lint::Level; -use std::collections::hash_map; use std::ops::Bound; pub struct UnsafetyChecker<'a, 'tcx> { @@ -26,7 +25,7 @@ pub struct UnsafetyChecker<'a, 'tcx> { /// /// The keys are the used `unsafe` blocks, the UnusedUnsafeKind indicates whether /// or not any of the usages happen at a place that doesn't allow `unsafe_op_in_unsafe_fn`. - used_unsafe_blocks: FxHashMap, + used_unsafe_blocks: FxHashSet, } impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { @@ -130,10 +129,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { &AggregateKind::Closure(def_id, _) | &AggregateKind::Generator(def_id, _, _) => { let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } = self.tcx.unsafety_check_result(def_id); - self.register_violations( - violations, - used_unsafe_blocks.iter().map(|(&h, &d)| (h, d)), - ); + self.register_violations(violations, used_unsafe_blocks.iter().copied()); } }, _ => {} @@ -257,22 +253,8 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> { fn register_violations<'a>( &mut self, violations: impl IntoIterator, - new_used_unsafe_blocks: impl IntoIterator, + new_used_unsafe_blocks: impl IntoIterator, ) { - use UsedUnsafeBlockData::*; - - let update_entry = |this: &mut Self, hir_id, new_usage| { - match this.used_unsafe_blocks.entry(hir_id) { - hash_map::Entry::Occupied(mut entry) => { - if new_usage == SomeDisallowedInUnsafeFn { - *entry.get_mut() = SomeDisallowedInUnsafeFn; - } - } - hash_map::Entry::Vacant(entry) => { - entry.insert(new_usage); - } - }; - }; let safety = self.body.source_scopes[self.source_info.scope] .local_data .as_ref() @@ -300,17 +282,13 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> { }), Safety::BuiltinUnsafe => {} Safety::ExplicitUnsafe(hir_id) => violations.into_iter().for_each(|_violation| { - update_entry( - self, - hir_id, - SomeDisallowedInUnsafeFn, - ) + self.used_unsafe_blocks.insert(hir_id); }), }; - new_used_unsafe_blocks - .into_iter() - .for_each(|(hir_id, usage_data)| update_entry(self, hir_id, usage_data)); + new_used_unsafe_blocks.into_iter().for_each(|hir_id| { + self.used_unsafe_blocks.insert(hir_id); + }); } fn check_mut_borrowing_layout_constrained_field( &mut self, @@ -407,34 +385,28 @@ enum Context { struct UnusedUnsafeVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, - used_unsafe_blocks: &'a FxHashMap, + used_unsafe_blocks: &'a FxHashSet, context: Context, unused_unsafes: &'a mut Vec<(HirId, UnusedUnsafe)>, } impl<'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'_, 'tcx> { fn visit_block(&mut self, block: &'tcx hir::Block<'tcx>) { - use UsedUnsafeBlockData::{AllAllowedInUnsafeFn, SomeDisallowedInUnsafeFn}; - if let hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) = block.rules { let used = match self.tcx.lint_level_at_node(UNUSED_UNSAFE, block.hir_id) { - (Level::Allow, _) => Some(SomeDisallowedInUnsafeFn), - _ => self.used_unsafe_blocks.get(&block.hir_id).copied(), + (Level::Allow, _) => true, + _ => self.used_unsafe_blocks.contains(&block.hir_id), }; let unused_unsafe = match (self.context, used) { - (_, None) => UnusedUnsafe::Unused, - (Context::Safe, Some(_)) - | (Context::UnsafeFn(_), Some(SomeDisallowedInUnsafeFn)) => { + (_, false) => UnusedUnsafe::Unused, + (Context::Safe, true) | (Context::UnsafeFn(_), true) => { let previous_context = self.context; self.context = Context::UnsafeBlock(block.hir_id); intravisit::walk_block(self, block); self.context = previous_context; return; } - (Context::UnsafeFn(hir_id), Some(AllAllowedInUnsafeFn(lint_root))) => { - UnusedUnsafe::InUnsafeFn(hir_id, lint_root) - } - (Context::UnsafeBlock(hir_id), Some(_)) => UnusedUnsafe::InUnsafeBlock(hir_id), + (Context::UnsafeBlock(hir_id), true) => UnusedUnsafe::InUnsafeBlock(hir_id), }; self.unused_unsafes.push((block.hir_id, unused_unsafe)); } @@ -458,7 +430,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'_, 'tcx> { fn check_unused_unsafe( tcx: TyCtxt<'_>, def_id: LocalDefId, - used_unsafe_blocks: &FxHashMap, + used_unsafe_blocks: &FxHashSet, ) -> Vec<(HirId, UnusedUnsafe)> { let body_id = tcx.hir().maybe_body_owned_by(def_id); @@ -518,11 +490,6 @@ fn unsafety_check_result<'tcx>( } fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) { - if matches!(kind, UnusedUnsafe::InUnsafeFn(..)) { - // We do *not* warn here, these unsafe blocks are actually required when - // `unsafe_op_in_unsafe_fn` is warn or higher. - return; - } let span = tcx.sess.source_map().guess_head_span(tcx.hir().span(id)); tcx.struct_span_lint_hir(UNUSED_UNSAFE, id, span, |lint| { let msg = "unnecessary `unsafe` block"; @@ -536,7 +503,6 @@ fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) { "because it's nested under this `unsafe` block", ); } - UnusedUnsafe::InUnsafeFn(_id, _usage_lint_root) => unreachable!(), } db.emit(); -- cgit 1.4.1-3-g733a5 From 35a35d86fdca99b22b07ed7d998ce05032e800d4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 2 Aug 2022 18:55:43 -0400 Subject: update comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Léo Lanteri Thauvin --- compiler/rustc_mir_transform/src/check_unsafety.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index a9eb60c7a15..0f5fd77f7ab 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -22,9 +22,6 @@ pub struct UnsafetyChecker<'a, 'tcx> { param_env: ty::ParamEnv<'tcx>, /// Used `unsafe` blocks in this function. This is used for the "unused_unsafe" lint. - /// - /// The keys are the used `unsafe` blocks, the UnusedUnsafeKind indicates whether - /// or not any of the usages happen at a place that doesn't allow `unsafe_op_in_unsafe_fn`. used_unsafe_blocks: FxHashSet, } -- cgit 1.4.1-3-g733a5 From 86e2ca30880a06cb9dbcef1db4a20266e54cf862 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 2 Aug 2022 18:57:22 -0400 Subject: add link to discussion --- compiler/rustc_mir_build/src/check_unsafety.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index e3157a43001..f0b0456c4b9 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -77,7 +77,8 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { SafetyContext::UnsafeBlock { ref mut used, .. } => { // Mark this block as useful (even inside `unsafe fn`, where it is technically // redundant -- but we want to eventually enable `unsafe_op_in_unsafe_fn` by - // default which will require those blocks). + // default which will require those blocks: + // https://github.com/rust-lang/rust/issues/71668#issuecomment-1203075594). *used = true; } SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {} -- cgit 1.4.1-3-g733a5 From 8c8fc6af33c0a10340535fb9eb6ab9b7648bf742 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Tue, 2 Aug 2022 08:08:45 +0100 Subject: Use native cranelift instructions when lowering float intrinsics --- src/intrinsics/mod.rs | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index f552c13958d..77caf741acf 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -301,7 +301,38 @@ fn codegen_float_intrinsic_call<'tcx>( _ => unreachable!(), }; - let res = fx.easy_call(name, &args, ty); + let layout = fx.layout_of(ty); + let res = match intrinsic { + sym::copysignf32 | sym::copysignf64 => { + let a = args[0].load_scalar(fx); + let b = args[1].load_scalar(fx); + CValue::by_val(fx.bcx.ins().fcopysign(a, b), layout) + } + sym::fabsf32 + | sym::fabsf64 + | sym::floorf32 + | sym::floorf64 + | sym::ceilf32 + | sym::ceilf64 + | sym::truncf32 + | sym::truncf64 => { + let a = args[0].load_scalar(fx); + + let val = match intrinsic { + sym::fabsf32 | sym::fabsf64 => fx.bcx.ins().fabs(a), + sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(a), + sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(a), + sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(a), + _ => unreachable!(), + }; + + CValue::by_val(val, layout) + } + // These intrinsics aren't supported natively by Cranelift. + // Lower them to a libcall. + _ => fx.easy_call(name, &args, ty), + }; + ret.write_cvalue(fx, res); true -- cgit 1.4.1-3-g733a5 From 39bc74e8b80a08fcf041622f87b0b4b52a1c0ffe Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 23 May 2022 17:20:48 +0200 Subject: Make object_lifetime_defaults a cross-crate query. --- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_resolve/src/late/lifetimes.rs | 60 +++++++++------------------- 2 files changed, 20 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index d8483e7e409..34639c0b0d0 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1579,7 +1579,7 @@ rustc_queries! { /// for each parameter if a trait object were to be passed for that parameter. /// For example, for `struct Foo<'a, T, U>`, this would be `['static, 'static]`. /// For `struct Foo<'a, T: 'a, U>`, this would instead be `['a, 'static]`. - query object_lifetime_defaults(_: LocalDefId) -> Option<&'tcx [ObjectLifetimeDefault]> { + query object_lifetime_defaults(_: DefId) -> Option<&'tcx [ObjectLifetimeDefault]> { desc { "looking up lifetime defaults for a region on an item" } } query late_bound_vars_map(_: LocalDefId) diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 94460e33d8b..f52db86733b 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -11,7 +11,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{DefIdMap, LocalDefId}; +use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeName, Node}; use rustc_middle::bug; @@ -24,7 +24,6 @@ use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use std::borrow::Cow; use std::fmt; -use std::mem::take; trait RegionExt { fn early(hir_map: Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (LocalDefId, Region); @@ -131,9 +130,6 @@ pub(crate) struct LifetimeContext<'a, 'tcx> { /// be false if the `Item` we are resolving lifetimes for is not a trait or /// we eventually need lifetimes resolve for trait items. trait_definition_only: bool, - - /// Cache for cross-crate per-definition object lifetime defaults. - xcrate_object_lifetime_defaults: DefIdMap>, } #[derive(Debug)] @@ -294,9 +290,23 @@ pub fn provide(providers: &mut ty::query::Providers) { named_region_map: |tcx, id| resolve_lifetimes_for(tcx, id).defs.get(&id), is_late_bound_map, - object_lifetime_defaults: |tcx, id| match tcx.hir().find_by_def_id(id) { - Some(Node::Item(item)) => compute_object_lifetime_defaults(tcx, item), - _ => None, + object_lifetime_defaults: |tcx, def_id| { + if let Some(def_id) = def_id.as_local() { + match tcx.hir().get_by_def_id(def_id) { + Node::Item(item) => compute_object_lifetime_defaults(tcx, item), + _ => None, + } + } else { + Some(tcx.arena.alloc_from_iter(tcx.generics_of(def_id).params.iter().filter_map( + |param| match param.kind { + GenericParamDefKind::Type { object_lifetime_default, .. } => { + Some(object_lifetime_default) + } + GenericParamDefKind::Const { .. } => Some(Set1::Empty), + GenericParamDefKind::Lifetime => None, + }, + ))) + } }, late_bound_vars_map: |tcx, id| resolve_lifetimes_for(tcx, id).late_bound_vars.get(&id), @@ -363,7 +373,6 @@ fn do_resolve( map: &mut named_region_map, scope: ROOT_SCOPE, trait_definition_only, - xcrate_object_lifetime_defaults: Default::default(), }; visitor.visit_item(item); @@ -1413,20 +1422,17 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { F: for<'b> FnOnce(&mut LifetimeContext<'b, 'tcx>), { let LifetimeContext { tcx, map, .. } = self; - let xcrate_object_lifetime_defaults = take(&mut self.xcrate_object_lifetime_defaults); let mut this = LifetimeContext { tcx: *tcx, map, scope: &wrap_scope, trait_definition_only: self.trait_definition_only, - xcrate_object_lifetime_defaults, }; let span = tracing::debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope)); { let _enter = span.enter(); f(&mut this); } - self.xcrate_object_lifetime_defaults = this.xcrate_object_lifetime_defaults; } /// Visits self by adding a scope and handling recursive walk over the contents with `walk`. @@ -1780,35 +1786,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } Set1::Many => None, }; - if let Some(def_id) = def_id.as_local() { - let id = self.tcx.hir().local_def_id_to_hir_id(def_id); - self.tcx - .object_lifetime_defaults(id.owner) - .unwrap() - .iter() - .map(set_to_region) - .collect() - } else { - let tcx = self.tcx; - self.xcrate_object_lifetime_defaults - .entry(def_id) - .or_insert_with(|| { - tcx.generics_of(def_id) - .params - .iter() - .filter_map(|param| match param.kind { - GenericParamDefKind::Type { object_lifetime_default, .. } => { - Some(object_lifetime_default) - } - GenericParamDefKind::Const { .. } => Some(Set1::Empty), - GenericParamDefKind::Lifetime => None, - }) - .collect() - }) - .iter() - .map(set_to_region) - .collect() - } + self.tcx.object_lifetime_defaults(def_id).unwrap().iter().map(set_to_region).collect() }); debug!("visit_segment_args: object_lifetime_defaults={:?}", object_lifetime_defaults); -- cgit 1.4.1-3-g733a5 From 236ccce79e71020350b8e2d7a263807f02eb6e8e Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 24 May 2022 12:51:59 +0200 Subject: Create a specific `ObjectLifetimeDefault` enum. --- compiler/rustc_middle/src/hir/map/mod.rs | 8 +- .../rustc_middle/src/middle/resolve_lifetime.rs | 8 +- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_resolve/src/late/lifetimes.rs | 112 +++++++-------------- compiler/rustc_typeck/src/astconv/mod.rs | 2 - compiler/rustc_typeck/src/collect.rs | 9 +- 6 files changed, 58 insertions(+), 83 deletions(-) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 47b04c33ec1..df0687b2224 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -499,7 +499,9 @@ impl<'hir> Map<'hir> { let def_kind = self.tcx.def_kind(def_id); match def_kind { DefKind::Trait | DefKind::TraitAlias => def_id, - DefKind::TyParam | DefKind::ConstParam => self.tcx.local_parent(def_id), + DefKind::LifetimeParam | DefKind::TyParam | DefKind::ConstParam => { + self.tcx.local_parent(def_id) + } _ => bug!("ty_param_owner: {:?} is a {:?} not a type parameter", def_id, def_kind), } } @@ -508,7 +510,9 @@ impl<'hir> Map<'hir> { let def_kind = self.tcx.def_kind(def_id); match def_kind { DefKind::Trait | DefKind::TraitAlias => kw::SelfUpper, - DefKind::TyParam | DefKind::ConstParam => self.tcx.item_name(def_id.to_def_id()), + DefKind::LifetimeParam | DefKind::TyParam | DefKind::ConstParam => { + self.tcx.item_name(def_id.to_def_id()) + } _ => bug!("ty_param_name: {:?} is a {:?} not a type parameter", def_id, def_kind), } } diff --git a/compiler/rustc_middle/src/middle/resolve_lifetime.rs b/compiler/rustc_middle/src/middle/resolve_lifetime.rs index 9b2f4456705..05f4ab487ef 100644 --- a/compiler/rustc_middle/src/middle/resolve_lifetime.rs +++ b/compiler/rustc_middle/src/middle/resolve_lifetime.rs @@ -35,7 +35,13 @@ impl Set1 { } } -pub type ObjectLifetimeDefault = Set1; +#[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)] +pub enum ObjectLifetimeDefault { + Empty, + Static, + Ambiguous, + Param(DefId), +} /// Maps the id of each lifetime reference to the lifetime decl /// that it corresponds to. diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 34639c0b0d0..d8483e7e409 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1579,7 +1579,7 @@ rustc_queries! { /// for each parameter if a trait object were to be passed for that parameter. /// For example, for `struct Foo<'a, T, U>`, this would be `['static, 'static]`. /// For `struct Foo<'a, T: 'a, U>`, this would instead be `['a, 'static]`. - query object_lifetime_defaults(_: DefId) -> Option<&'tcx [ObjectLifetimeDefault]> { + query object_lifetime_defaults(_: LocalDefId) -> Option<&'tcx [ObjectLifetimeDefault]> { desc { "looking up lifetime defaults for a region on an item" } } query late_bound_vars_map(_: LocalDefId) diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index f52db86733b..b96968f81e0 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -290,24 +290,7 @@ pub fn provide(providers: &mut ty::query::Providers) { named_region_map: |tcx, id| resolve_lifetimes_for(tcx, id).defs.get(&id), is_late_bound_map, - object_lifetime_defaults: |tcx, def_id| { - if let Some(def_id) = def_id.as_local() { - match tcx.hir().get_by_def_id(def_id) { - Node::Item(item) => compute_object_lifetime_defaults(tcx, item), - _ => None, - } - } else { - Some(tcx.arena.alloc_from_iter(tcx.generics_of(def_id).params.iter().filter_map( - |param| match param.kind { - GenericParamDefKind::Type { object_lifetime_default, .. } => { - Some(object_lifetime_default) - } - GenericParamDefKind::Const { .. } => Some(Set1::Empty), - GenericParamDefKind::Lifetime => None, - }, - ))) - } - }, + object_lifetime_defaults, late_bound_vars_map: |tcx, id| resolve_lifetimes_for(tcx, id).late_bound_vars.get(&id), ..*providers @@ -1281,10 +1264,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } -fn compute_object_lifetime_defaults<'tcx>( +fn object_lifetime_defaults<'tcx>( tcx: TyCtxt<'tcx>, - item: &hir::Item<'_>, + def_id: LocalDefId, ) -> Option<&'tcx [ObjectLifetimeDefault]> { + let hir::Node::Item(item) = tcx.hir().get_by_def_id(def_id) else { return None; }; match item.kind { hir::ItemKind::Struct(_, ref generics) | hir::ItemKind::Union(_, ref generics) @@ -1304,24 +1288,13 @@ fn compute_object_lifetime_defaults<'tcx>( let object_lifetime_default_reprs: String = result .iter() .map(|set| match *set { - Set1::Empty => "BaseDefault".into(), - Set1::One(Region::Static) => "'static".into(), - Set1::One(Region::EarlyBound(mut i, _)) => generics - .params - .iter() - .find_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - if i == 0 { - return Some(param.name.ident().to_string().into()); - } - i -= 1; - None - } - _ => None, - }) - .unwrap(), - Set1::One(_) => bug!(), - Set1::Many => "Ambiguous".into(), + ObjectLifetimeDefault::Empty => "BaseDefault".into(), + ObjectLifetimeDefault::Static => "'static".into(), + ObjectLifetimeDefault::Param(def_id) => { + let def_id = def_id.expect_local(); + tcx.hir().ty_param_name(def_id).to_string().into() + } + ObjectLifetimeDefault::Ambiguous => "Ambiguous".into(), }) .collect::>>() .join(","); @@ -1376,32 +1349,12 @@ fn object_lifetime_defaults_for_item<'tcx>( } Some(match set { - Set1::Empty => Set1::Empty, - Set1::One(name) => { - if name == hir::LifetimeName::Static { - Set1::One(Region::Static) - } else { - generics - .params - .iter() - .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - let param_def_id = tcx.hir().local_def_id(param.hir_id); - Some(( - param_def_id, - hir::LifetimeName::Param(param_def_id, param.name), - )) - } - _ => None, - }) - .enumerate() - .find(|&(_, (_, lt_name))| lt_name == name) - .map_or(Set1::Many, |(i, (def_id, _))| { - Set1::One(Region::EarlyBound(i as u32, def_id.to_def_id())) - }) - } + Set1::Empty => ObjectLifetimeDefault::Empty, + Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static, + Set1::One(hir::LifetimeName::Param(param_def_id, _)) => { + ObjectLifetimeDefault::Param(param_def_id.to_def_id()) } - Set1::Many => Set1::Many, + _ => ObjectLifetimeDefault::Ambiguous, }) } GenericParamKind::Const { .. } => { @@ -1409,7 +1362,7 @@ fn object_lifetime_defaults_for_item<'tcx>( // // We still store a dummy value here to allow generic parameters // in an arbitrary order. - Some(Set1::Empty) + Some(ObjectLifetimeDefault::Empty) } }; @@ -1769,24 +1722,37 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { }; let map = &self.map; - let set_to_region = |set: &ObjectLifetimeDefault| match *set { - Set1::Empty => { + let generics = self.tcx.generics_of(def_id); + let set_to_region = |set: ObjectLifetimeDefault| match set { + ObjectLifetimeDefault::Empty => { if in_body { None } else { Some(Region::Static) } } - Set1::One(r) => { - let lifetimes = generic_args.args.iter().filter_map(|arg| match arg { - GenericArg::Lifetime(lt) => Some(lt), + ObjectLifetimeDefault::Static => Some(Region::Static), + ObjectLifetimeDefault::Param(param_def_id) => { + let index = generics.param_def_id_to_index[¶m_def_id]; + generic_args.args.get(index as usize).and_then(|arg| match arg { + GenericArg::Lifetime(lt) => map.defs.get(<.hir_id).copied(), _ => None, - }); - r.subst(lifetimes, map) + }) } - Set1::Many => None, + ObjectLifetimeDefault::Ambiguous => None, }; - self.tcx.object_lifetime_defaults(def_id).unwrap().iter().map(set_to_region).collect() + generics + .params + .iter() + .filter_map(|param| match param.kind { + GenericParamDefKind::Type { object_lifetime_default, .. } => { + Some(object_lifetime_default) + } + GenericParamDefKind::Const { .. } => Some(ObjectLifetimeDefault::Empty), + GenericParamDefKind::Lifetime => None, + }) + .map(set_to_region) + .collect() }); debug!("visit_segment_args: object_lifetime_defaults={:?}", object_lifetime_defaults); diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 8a5c7fee697..ee184a09391 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -252,9 +252,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }) } }; - debug!("ast_region_to_region(lifetime={:?}) yields {:?}", lifetime, r); - r } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 99996e80c9c..1c1df4a2f7f 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -34,6 +34,7 @@ use rustc_hir::weak_lang_items; use rustc_hir::{GenericParamKind, HirId, Node}; use rustc_middle::hir::nested_filter; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; +use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault; use rustc_middle::mir::mono::Linkage; use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::InternalSubsts; @@ -1597,7 +1598,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { has_default: false, - object_lifetime_default: rl::Set1::Empty, + object_lifetime_default: ObjectLifetimeDefault::Empty, synthetic: false, }, }); @@ -1671,7 +1672,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { has_default: default.is_some(), object_lifetime_default: object_lifetime_defaults .as_ref() - .map_or(rl::Set1::Empty, |o| o[i]), + .map_or(ObjectLifetimeDefault::Empty, |o| o[i]), synthetic, }; @@ -1727,7 +1728,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { has_default: false, - object_lifetime_default: rl::Set1::Empty, + object_lifetime_default: ObjectLifetimeDefault::Empty, synthetic: false, }, })); @@ -1744,7 +1745,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { has_default: false, - object_lifetime_default: rl::Set1::Empty, + object_lifetime_default: ObjectLifetimeDefault::Empty, synthetic: false, }, }); -- cgit 1.4.1-3-g733a5 From 99e2d33315afa0168e971d929667dde0158200e7 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 29 May 2022 20:15:34 +0200 Subject: Compute `object_lifetime_default` per parameter. --- .../src/rmeta/decoder/cstore_impl.rs | 1 + compiler/rustc_metadata/src/rmeta/encoder.rs | 5 + compiler/rustc_metadata/src/rmeta/mod.rs | 2 + compiler/rustc_middle/src/query/mod.rs | 5 +- compiler/rustc_middle/src/ty/generics.rs | 3 +- compiler/rustc_middle/src/ty/parameterized.rs | 1 + compiler/rustc_passes/src/check_attr.rs | 28 ++++++ compiler/rustc_resolve/src/late/lifetimes.rs | 108 +++++---------------- compiler/rustc_typeck/src/collect.rs | 24 +---- 9 files changed, 68 insertions(+), 109 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 38ce50e8323..14a28cf7d3f 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -199,6 +199,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, codegen_fn_attrs => { table } impl_trait_ref => { table } const_param_default => { table } + object_lifetime_default => { table } thir_abstract_const => { table } optimized_mir => { table } mir_for_ctfe => { table } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 33278367ce3..50a309f8785 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1044,6 +1044,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record_array!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives); } } + if let DefKind::TyParam | DefKind::ConstParam = def_kind { + if let Some(default) = self.tcx.object_lifetime_default(def_id) { + record!(self.tables.object_lifetime_default[def_id] <- default); + } + } if let DefKind::Trait | DefKind::TraitAlias = def_kind { record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id)); } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 66bdecc30db..2f3493d1b19 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -16,6 +16,7 @@ use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec}; use rustc_middle::metadata::ModChild; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; +use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault; use rustc_middle::mir; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::query::Providers; @@ -357,6 +358,7 @@ define_tables! { codegen_fn_attrs: Table>, impl_trait_ref: Table>>, const_param_default: Table>>, + object_lifetime_default: Table>, optimized_mir: Table>>, mir_for_ctfe: Table>>, promoted_mir: Table>>>, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index d8483e7e409..ff296116a1f 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1579,8 +1579,9 @@ rustc_queries! { /// for each parameter if a trait object were to be passed for that parameter. /// For example, for `struct Foo<'a, T, U>`, this would be `['static, 'static]`. /// For `struct Foo<'a, T: 'a, U>`, this would instead be `['a, 'static]`. - query object_lifetime_defaults(_: LocalDefId) -> Option<&'tcx [ObjectLifetimeDefault]> { - desc { "looking up lifetime defaults for a region on an item" } + query object_lifetime_default(key: DefId) -> Option { + desc { "looking up lifetime defaults for generic parameter `{:?}`", key } + separate_provide_extern } query late_bound_vars_map(_: LocalDefId) -> Option<&'tcx FxHashMap>> { diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index add2df25884..d6a55af51e5 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -1,4 +1,3 @@ -use crate::middle::resolve_lifetime::ObjectLifetimeDefault; use crate::ty; use crate::ty::subst::{Subst, SubstsRef}; use crate::ty::EarlyBinder; @@ -13,7 +12,7 @@ use super::{EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Predi #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] pub enum GenericParamDefKind { Lifetime, - Type { has_default: bool, object_lifetime_default: ObjectLifetimeDefault, synthetic: bool }, + Type { has_default: bool, synthetic: bool }, Const { has_default: bool }, } diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index e189ee2fc4d..067ad927a03 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -53,6 +53,7 @@ trivially_parameterized_over_tcx! { crate::metadata::ModChild, crate::middle::codegen_fn_attrs::CodegenFnAttrs, crate::middle::exported_symbols::SymbolExportInfo, + crate::middle::resolve_lifetime::ObjectLifetimeDefault, crate::mir::ConstQualifs, ty::Generics, ty::ImplPolarity, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index fde12b9eee6..33ab2e12edd 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -16,6 +16,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID}; use rustc_hir::{MethodKind, Target}; use rustc_middle::hir::nested_filter; +use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::lint::builtin::{ @@ -171,6 +172,9 @@ impl CheckAttrVisitor<'_> { sym::no_implicit_prelude => { self.check_generic_attr(hir_id, attr, target, &[Target::Mod]) } + sym::rustc_object_lifetime_default => { + self.check_object_lifetime_default(hir_id, span) + } _ => {} } @@ -402,6 +406,30 @@ impl CheckAttrVisitor<'_> { } } + /// Debugging aid for `object_lifetime_default` query. + fn check_object_lifetime_default(&self, hir_id: HirId, span: Span) { + let tcx = self.tcx; + if let Some(generics) = tcx.hir().get_generics(tcx.hir().local_def_id(hir_id)) { + let object_lifetime_default_reprs: String = generics + .params + .iter() + .filter_map(|p| { + let param_id = tcx.hir().local_def_id(p.hir_id); + let default = tcx.object_lifetime_default(param_id)?; + Some(match default { + ObjectLifetimeDefault::Empty => "BaseDefault".to_owned(), + ObjectLifetimeDefault::Static => "'static".to_owned(), + ObjectLifetimeDefault::Param(def_id) => tcx.item_name(def_id).to_string(), + ObjectLifetimeDefault::Ambiguous => "Ambiguous".to_owned(), + }) + }) + .collect::>() + .join(","); + + tcx.sess.span_err(span, &object_lifetime_default_reprs); + } + } + /// Checks if a `#[track_caller]` is applied to a non-naked function. Returns `true` if valid. fn check_track_caller( &self, diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index b96968f81e0..52980f15971 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -18,11 +18,10 @@ use rustc_middle::bug; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_lifetime::*; -use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt}; +use rustc_middle::ty::{self, DefIdTree, TyCtxt}; use rustc_span::def_id::DefId; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; -use std::borrow::Cow; use std::fmt; trait RegionExt { @@ -290,7 +289,7 @@ pub fn provide(providers: &mut ty::query::Providers) { named_region_map: |tcx, id| resolve_lifetimes_for(tcx, id).defs.get(&id), is_late_bound_map, - object_lifetime_defaults, + object_lifetime_default, late_bound_vars_map: |tcx, id| resolve_lifetimes_for(tcx, id).late_bound_vars.get(&id), ..*providers @@ -1264,87 +1263,36 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } -fn object_lifetime_defaults<'tcx>( +fn object_lifetime_default<'tcx>( tcx: TyCtxt<'tcx>, - def_id: LocalDefId, -) -> Option<&'tcx [ObjectLifetimeDefault]> { - let hir::Node::Item(item) = tcx.hir().get_by_def_id(def_id) else { return None; }; - match item.kind { - hir::ItemKind::Struct(_, ref generics) - | hir::ItemKind::Union(_, ref generics) - | hir::ItemKind::Enum(_, ref generics) - | hir::ItemKind::OpaqueTy(hir::OpaqueTy { - ref generics, - origin: hir::OpaqueTyOrigin::TyAlias, - .. - }) - | hir::ItemKind::TyAlias(_, ref generics) - | hir::ItemKind::Trait(_, _, ref generics, ..) => { - let result = object_lifetime_defaults_for_item(tcx, generics); - - // Debugging aid. - let attrs = tcx.hir().attrs(item.hir_id()); - if tcx.sess.contains_name(attrs, sym::rustc_object_lifetime_default) { - let object_lifetime_default_reprs: String = result - .iter() - .map(|set| match *set { - ObjectLifetimeDefault::Empty => "BaseDefault".into(), - ObjectLifetimeDefault::Static => "'static".into(), - ObjectLifetimeDefault::Param(def_id) => { - let def_id = def_id.expect_local(); - tcx.hir().ty_param_name(def_id).to_string().into() - } - ObjectLifetimeDefault::Ambiguous => "Ambiguous".into(), - }) - .collect::>>() - .join(","); - tcx.sess.span_err(item.span, &object_lifetime_default_reprs); - } - - Some(result) - } - _ => None, - } -} - -/// Scan the bounds and where-clauses on parameters to extract bounds -/// of the form `T:'a` so as to determine the `ObjectLifetimeDefault` -/// for each type parameter. -fn object_lifetime_defaults_for_item<'tcx>( - tcx: TyCtxt<'tcx>, - generics: &hir::Generics<'_>, -) -> &'tcx [ObjectLifetimeDefault] { - fn add_bounds(set: &mut Set1, bounds: &[hir::GenericBound<'_>]) { - for bound in bounds { - if let hir::GenericBound::Outlives(ref lifetime) = *bound { - set.insert(lifetime.name.normalize_to_macros_2_0()); - } - } - } - - let process_param = |param: &hir::GenericParam<'_>| match param.kind { + param_def_id: DefId, +) -> Option { + let param_def_id = param_def_id.expect_local(); + let parent_def_id = tcx.local_parent(param_def_id); + let generics = tcx.hir().get_generics(parent_def_id)?; + let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id); + let param = generics.params.iter().find(|p| p.hir_id == param_hir_id)?; + + // Scan the bounds and where-clauses on parameters to extract bounds + // of the form `T:'a` so as to determine the `ObjectLifetimeDefault` + // for each type parameter. + match param.kind { GenericParamKind::Lifetime { .. } => None, GenericParamKind::Type { .. } => { let mut set = Set1::Empty; - let param_def_id = tcx.hir().local_def_id(param.hir_id); - for predicate in generics.predicates { - // Look for `type: ...` where clauses. - let hir::WherePredicate::BoundPredicate(ref data) = *predicate else { continue }; - + // Look for `type: ...` where clauses. + for bound in generics.bounds_for_param(param_def_id) { // Ignore `for<'a> type: ...` as they can change what // lifetimes mean (although we could "just" handle it). - if !data.bound_generic_params.is_empty() { + if !bound.bound_generic_params.is_empty() { continue; } - let res = match data.bounded_ty.kind { - hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => path.res, - _ => continue, - }; - - if res == Res::Def(DefKind::TyParam, param_def_id.to_def_id()) { - add_bounds(&mut set, &data.bounds); + for bound in bound.bounds { + if let hir::GenericBound::Outlives(ref lifetime) = *bound { + set.insert(lifetime.name.normalize_to_macros_2_0()); + } } } @@ -1364,9 +1312,7 @@ fn object_lifetime_defaults_for_item<'tcx>( // in an arbitrary order. Some(ObjectLifetimeDefault::Empty) } - }; - - tcx.arena.alloc_from_iter(generics.params.iter().filter_map(process_param)) + } } impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { @@ -1744,13 +1690,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { generics .params .iter() - .filter_map(|param| match param.kind { - GenericParamDefKind::Type { object_lifetime_default, .. } => { - Some(object_lifetime_default) - } - GenericParamDefKind::Const { .. } => Some(ObjectLifetimeDefault::Empty), - GenericParamDefKind::Lifetime => None, - }) + .filter_map(|param| self.tcx.object_lifetime_default(param.def_id)) .map(set_to_region) .collect() }); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 1c1df4a2f7f..0ec2acafd07 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -34,7 +34,6 @@ use rustc_hir::weak_lang_items; use rustc_hir::{GenericParamKind, HirId, Node}; use rustc_middle::hir::nested_filter; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; -use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault; use rustc_middle::mir::mono::Linkage; use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::InternalSubsts; @@ -1598,7 +1597,6 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { has_default: false, - object_lifetime_default: ObjectLifetimeDefault::Empty, synthetic: false, }, }); @@ -1642,8 +1640,6 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { kind: ty::GenericParamDefKind::Lifetime, })); - let object_lifetime_defaults = tcx.object_lifetime_defaults(hir_id.owner); - // Now create the real type and const parameters. let type_start = own_start - has_self as u32 + params.len() as u32; let mut i = 0; @@ -1668,13 +1664,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { } } - let kind = ty::GenericParamDefKind::Type { - has_default: default.is_some(), - object_lifetime_default: object_lifetime_defaults - .as_ref() - .map_or(ObjectLifetimeDefault::Empty, |o| o[i]), - synthetic, - }; + let kind = ty::GenericParamDefKind::Type { has_default: default.is_some(), synthetic }; let param_def = ty::GenericParamDef { index: type_start + i as u32, @@ -1726,11 +1716,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { name: Symbol::intern(arg), def_id, pure_wrt_drop: false, - kind: ty::GenericParamDefKind::Type { - has_default: false, - object_lifetime_default: ObjectLifetimeDefault::Empty, - synthetic: false, - }, + kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false }, })); } @@ -1743,11 +1729,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { name: Symbol::intern(""), def_id, pure_wrt_drop: false, - kind: ty::GenericParamDefKind::Type { - has_default: false, - object_lifetime_default: ObjectLifetimeDefault::Empty, - synthetic: false, - }, + kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false }, }); } } -- cgit 1.4.1-3-g733a5 From 63c3aabeb8fdde119384562341b2d3b201be54ed Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 24 May 2022 08:31:11 +0200 Subject: Create lifetime parameter like any other parameter. --- compiler/rustc_typeck/src/astconv/mod.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index ee184a09391..dd6831e44fd 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -221,9 +221,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx.mk_region(ty::ReLateBound(debruijn, br)) } - Some(rl::Region::EarlyBound(index, id)) => { - let name = lifetime_name(id.expect_local()); - tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { def_id: id, index, name })) + Some(rl::Region::EarlyBound(_, def_id)) => { + let name = tcx.hir().ty_param_name(def_id.expect_local()); + let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local()); + let generics = tcx.generics_of(item_def_id); + let index = generics.param_def_id_to_index[&def_id]; + tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name })) } Some(rl::Region::Free(scope, id)) => { -- cgit 1.4.1-3-g733a5 From 421bb6ac62f5624a05d9e4ff0a12c91da91e49a8 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 24 May 2022 13:00:36 +0200 Subject: Remove index from Region::EarlyBound. --- .../nice_region_error/find_anon_type.rs | 8 +- compiler/rustc_lint/src/builtin.rs | 19 +- .../rustc_middle/src/middle/resolve_lifetime.rs | 2 +- compiler/rustc_resolve/src/late/lifetimes.rs | 223 +++------------------ compiler/rustc_typeck/src/astconv/mod.rs | 10 +- src/librustdoc/clean/mod.rs | 2 +- 6 files changed, 50 insertions(+), 214 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs index c1b201da691..ddad72fdab9 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -103,7 +103,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { // Find the index of the named region that was part of the // error. We will then search the function parameters for a bound // region at the right depth with the same index - (Some(rl::Region::EarlyBound(_, id)), ty::BrNamed(def_id, _)) => { + (Some(rl::Region::EarlyBound(id)), ty::BrNamed(def_id, _)) => { debug!("EarlyBound id={:?} def_id={:?}", id, def_id); if id == def_id { self.found_type = Some(arg); @@ -133,7 +133,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { Some( rl::Region::Static | rl::Region::Free(_, _) - | rl::Region::EarlyBound(_, _) + | rl::Region::EarlyBound(_) | rl::Region::LateBound(_, _, _), ) | None, @@ -188,7 +188,7 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> { fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) { match (self.tcx.named_region(lifetime.hir_id), self.bound_region) { // the lifetime of the TyPath! - (Some(rl::Region::EarlyBound(_, id)), ty::BrNamed(def_id, _)) => { + (Some(rl::Region::EarlyBound(id)), ty::BrNamed(def_id, _)) => { debug!("EarlyBound id={:?} def_id={:?}", id, def_id); if id == def_id { self.found_it = true; @@ -209,7 +209,7 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> { ( Some( rl::Region::Static - | rl::Region::EarlyBound(_, _) + | rl::Region::EarlyBound(_) | rl::Region::LateBound(_, _, _) | rl::Region::Free(_, _), ) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index bd58021f78f..7c49749137d 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2039,13 +2039,13 @@ declare_lint_pass!(ExplicitOutlivesRequirements => [EXPLICIT_OUTLIVES_REQUIREMEN impl ExplicitOutlivesRequirements { fn lifetimes_outliving_lifetime<'tcx>( inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)], - index: u32, + def_id: DefId, ) -> Vec> { inferred_outlives .iter() .filter_map(|(pred, _)| match pred.kind().skip_binder() { ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match *a { - ty::ReEarlyBound(ebr) if ebr.index == index => Some(b), + ty::ReEarlyBound(ebr) if ebr.def_id == def_id => Some(b), _ => None, }, _ => None, @@ -2082,8 +2082,12 @@ impl ExplicitOutlivesRequirements { .filter_map(|(i, bound)| { if let hir::GenericBound::Outlives(lifetime) = bound { let is_inferred = match tcx.named_region(lifetime.hir_id) { - Some(Region::EarlyBound(index, ..)) => inferred_outlives.iter().any(|r| { - if let ty::ReEarlyBound(ebr) = **r { ebr.index == index } else { false } + Some(Region::EarlyBound(def_id)) => inferred_outlives.iter().any(|r| { + if let ty::ReEarlyBound(ebr) = **r { + ebr.def_id == def_id + } else { + false + } }), _ => false, }; @@ -2177,11 +2181,14 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { for (i, where_predicate) in hir_generics.predicates.iter().enumerate() { let (relevant_lifetimes, bounds, span, in_where_clause) = match where_predicate { hir::WherePredicate::RegionPredicate(predicate) => { - if let Some(Region::EarlyBound(index, ..)) = + if let Some(Region::EarlyBound(region_def_id)) = cx.tcx.named_region(predicate.lifetime.hir_id) { ( - Self::lifetimes_outliving_lifetime(inferred_outlives, index), + Self::lifetimes_outliving_lifetime( + inferred_outlives, + region_def_id, + ), &predicate.bounds, predicate.span, predicate.in_where_clause, diff --git a/compiler/rustc_middle/src/middle/resolve_lifetime.rs b/compiler/rustc_middle/src/middle/resolve_lifetime.rs index 05f4ab487ef..a171f5711dc 100644 --- a/compiler/rustc_middle/src/middle/resolve_lifetime.rs +++ b/compiler/rustc_middle/src/middle/resolve_lifetime.rs @@ -10,7 +10,7 @@ use rustc_macros::HashStable; #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)] pub enum Region { Static, - EarlyBound(/* index */ u32, /* lifetime decl */ DefId), + EarlyBound(/* lifetime decl */ DefId), LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* lifetime decl */ DefId), Free(DefId, /* lifetime decl */ DefId), } diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 52980f15971..01ada080b01 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -25,7 +25,7 @@ use rustc_span::Span; use std::fmt; trait RegionExt { - fn early(hir_map: Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (LocalDefId, Region); + fn early(hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region); fn late(index: u32, hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region); @@ -34,19 +34,13 @@ trait RegionExt { fn shifted(self, amount: u32) -> Region; fn shifted_out_to_binder(self, binder: ty::DebruijnIndex) -> Region; - - fn subst<'a, L>(self, params: L, map: &NamedRegionMap) -> Option - where - L: Iterator; } impl RegionExt for Region { - fn early(hir_map: Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (LocalDefId, Region) { - let i = *index; - *index += 1; + fn early(hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region) { let def_id = hir_map.local_def_id(param.hir_id); - debug!("Region::early: index={} def_id={:?}", i, def_id); - (def_id, Region::EarlyBound(i, def_id.to_def_id())) + debug!("Region::early: def_id={:?}", def_id); + (def_id, Region::EarlyBound(def_id.to_def_id())) } fn late(idx: u32, hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region) { @@ -63,9 +57,7 @@ impl RegionExt for Region { match *self { Region::Static => None, - Region::EarlyBound(_, id) | Region::LateBound(_, _, id) | Region::Free(_, id) => { - Some(id) - } + Region::EarlyBound(id) | Region::LateBound(_, _, id) | Region::Free(_, id) => Some(id), } } @@ -86,17 +78,6 @@ impl RegionExt for Region { _ => self, } } - - fn subst<'a, L>(self, mut params: L, map: &NamedRegionMap) -> Option - where - L: Iterator, - { - if let Region::EarlyBound(index, _) = self { - params.nth(index as usize).and_then(|lifetime| map.defs.get(&lifetime.hir_id).cloned()) - } else { - Some(self) - } - } } /// Maps the id of each lifetime reference to the lifetime decl @@ -142,25 +123,6 @@ enum Scope<'a> { /// for diagnostics. lifetimes: FxIndexMap, - /// if we extend this scope with another scope, what is the next index - /// we should use for an early-bound region? - next_early_index: u32, - - /// Whether or not this binder would serve as the parent - /// binder for opaque types introduced within. For example: - /// - /// ```text - /// fn foo<'a>() -> impl for<'b> Trait> - /// ``` - /// - /// Here, the opaque types we create for the `impl Trait` - /// and `impl Trait2` references will both have the `foo` item - /// as their parent. When we get to `impl Trait2`, we find - /// that it is nested within the `for<>` binder -- this flag - /// allows us to skip that when looking for the parent binder - /// of the resulting opaque type. - opaque_type_parent: bool, - scope_type: BinderScopeType, /// The late bound vars for a given item are stored by `HirId` to be @@ -240,19 +202,9 @@ struct TruncatedScopeDebug<'a>(&'a Scope<'a>); impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.0 { - Scope::Binder { - lifetimes, - next_early_index, - opaque_type_parent, - scope_type, - hir_id, - where_bound_origin, - s: _, - } => f + Scope::Binder { lifetimes, scope_type, hir_id, where_bound_origin, s: _ } => f .debug_struct("Binder") .field("lifetimes", lifetimes) - .field("next_early_index", next_early_index) - .field("opaque_type_parent", opaque_type_parent) .field("scope_type", scope_type) .field("hir_id", hir_id) .field("where_bound_origin", where_bound_origin) @@ -423,13 +375,6 @@ fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId { item } -/// In traits, there is an implicit `Self` type parameter which comes before the generics. -/// We have to account for this when computing the index of the other generic parameters. -/// This function returns whether there is such an implicit parameter defined on the given item. -fn sub_items_have_self_param(node: &hir::ItemKind<'_>) -> bool { - matches!(*node, hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..)) -} - fn late_region_as_bound_region<'tcx>(tcx: TyCtxt<'tcx>, region: &Region) -> ty::BoundVariableKind { match region { Region::LateBound(_, _, def_id) => { @@ -549,7 +494,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } - let next_early_index = self.next_early_index(); let (lifetimes, binders): (FxIndexMap, Vec<_>) = bound_generic_params .iter() @@ -567,8 +511,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { hir_id: e.hir_id, lifetimes, s: self.scope, - next_early_index, - opaque_type_parent: false, scope_type: BinderScopeType::Normal, where_bound_origin: None, }; @@ -594,7 +536,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } match item.kind { hir::ItemKind::Fn(_, ref generics, _) => { - self.visit_early_late(None, item.hir_id(), generics, |this| { + self.visit_early_late(item.hir_id(), generics, |this| { intravisit::walk_item(this, item); }); } @@ -661,31 +603,20 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { | hir::ItemKind::TraitAlias(ref generics, ..) | hir::ItemKind::Impl(hir::Impl { ref generics, .. }) => { // These kinds of items have only early-bound lifetime parameters. - let mut index = if sub_items_have_self_param(&item.kind) { - 1 // Self comes before lifetimes - } else { - 0 - }; - let mut non_lifetime_count = 0; let lifetimes = generics .params .iter() .filter_map(|param| match param.kind { GenericParamKind::Lifetime { .. } => { - Some(Region::early(self.tcx.hir(), &mut index, param)) - } - GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { - non_lifetime_count += 1; - None + Some(Region::early(self.tcx.hir(), param)) } + GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None, }) .collect(); self.map.late_bound_vars.insert(item.hir_id(), vec![]); let scope = Scope::Binder { hir_id: item.hir_id(), lifetimes, - next_early_index: index + non_lifetime_count, - opaque_type_parent: true, scope_type: BinderScopeType::Normal, s: ROOT_SCOPE, where_bound_origin: None, @@ -703,7 +634,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { match item.kind { hir::ForeignItemKind::Fn(_, _, ref generics) => { - self.visit_early_late(None, item.hir_id(), generics, |this| { + self.visit_early_late(item.hir_id(), generics, |this| { intravisit::walk_foreign_item(this, item); }) } @@ -720,7 +651,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { match ty.kind { hir::TyKind::BareFn(ref c) => { - let next_early_index = self.next_early_index(); let (lifetimes, binders): (FxIndexMap, Vec<_>) = c .generic_params .iter() @@ -737,8 +667,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { hir_id: ty.hir_id, lifetimes, s: self.scope, - next_early_index, - opaque_type_parent: false, scope_type: BinderScopeType::Normal, where_bound_origin: None, }; @@ -877,32 +805,23 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // We want to start our early-bound indices at the end of the parent scope, // not including any parent `impl Trait`s. - let mut index = self.next_early_index_for_opaque_type(); - debug!(?index); - let mut lifetimes = FxIndexMap::default(); - let mut non_lifetime_count = 0; debug!(?generics.params); for param in generics.params { match param.kind { GenericParamKind::Lifetime { .. } => { - let (def_id, reg) = Region::early(self.tcx.hir(), &mut index, ¶m); + let (def_id, reg) = Region::early(self.tcx.hir(), ¶m); lifetimes.insert(def_id, reg); } - GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { - non_lifetime_count += 1; - } + GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {} } } - let next_early_index = index + non_lifetime_count; self.map.late_bound_vars.insert(ty.hir_id, vec![]); let scope = Scope::Binder { hir_id: ty.hir_id, lifetimes, - next_early_index, s: self.scope, - opaque_type_parent: false, scope_type: BinderScopeType::Normal, where_bound_origin: None, }; @@ -924,39 +843,27 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { use self::hir::TraitItemKind::*; match trait_item.kind { Fn(_, _) => { - let tcx = self.tcx; - self.visit_early_late( - Some(tcx.hir().get_parent_item(trait_item.hir_id())), - trait_item.hir_id(), - &trait_item.generics, - |this| intravisit::walk_trait_item(this, trait_item), - ); + self.visit_early_late(trait_item.hir_id(), &trait_item.generics, |this| { + intravisit::walk_trait_item(this, trait_item) + }); } Type(bounds, ref ty) => { let generics = &trait_item.generics; - let mut index = self.next_early_index(); - debug!("visit_ty: index = {}", index); - let mut non_lifetime_count = 0; let lifetimes = generics .params .iter() .filter_map(|param| match param.kind { GenericParamKind::Lifetime { .. } => { - Some(Region::early(self.tcx.hir(), &mut index, param)) - } - GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { - non_lifetime_count += 1; - None + Some(Region::early(self.tcx.hir(), param)) } + GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None, }) .collect(); self.map.late_bound_vars.insert(trait_item.hir_id(), vec![]); let scope = Scope::Binder { hir_id: trait_item.hir_id(), lifetimes, - next_early_index: index + non_lifetime_count, s: self.scope, - opaque_type_parent: true, scope_type: BinderScopeType::Normal, where_bound_origin: None, }; @@ -984,40 +891,26 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) { use self::hir::ImplItemKind::*; match impl_item.kind { - Fn(..) => { - let tcx = self.tcx; - self.visit_early_late( - Some(tcx.hir().get_parent_item(impl_item.hir_id())), - impl_item.hir_id(), - &impl_item.generics, - |this| intravisit::walk_impl_item(this, impl_item), - ); - } + Fn(..) => self.visit_early_late(impl_item.hir_id(), &impl_item.generics, |this| { + intravisit::walk_impl_item(this, impl_item) + }), TyAlias(ref ty) => { let generics = &impl_item.generics; - let mut index = self.next_early_index(); - let mut non_lifetime_count = 0; - debug!("visit_ty: index = {}", index); let lifetimes: FxIndexMap = generics .params .iter() .filter_map(|param| match param.kind { GenericParamKind::Lifetime { .. } => { - Some(Region::early(self.tcx.hir(), &mut index, param)) - } - GenericParamKind::Const { .. } | GenericParamKind::Type { .. } => { - non_lifetime_count += 1; - None + Some(Region::early(self.tcx.hir(), param)) } + GenericParamKind::Const { .. } | GenericParamKind::Type { .. } => None, }) .collect(); self.map.late_bound_vars.insert(ty.hir_id, vec![]); let scope = Scope::Binder { hir_id: ty.hir_id, lifetimes, - next_early_index: index + non_lifetime_count, s: self.scope, - opaque_type_parent: true, scope_type: BinderScopeType::Normal, where_bound_origin: None, }; @@ -1120,7 +1013,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }) .unzip(); this.map.late_bound_vars.insert(bounded_ty.hir_id, binders.clone()); - let next_early_index = this.next_early_index(); // Even if there are no lifetimes defined here, we still wrap it in a binder // scope. If there happens to be a nested poly trait ref (an error), that // will be `Concatenating` anyways, so we don't have to worry about the depth @@ -1129,8 +1021,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { hir_id: bounded_ty.hir_id, lifetimes, s: this.scope, - next_early_index, - opaque_type_parent: false, scope_type: BinderScopeType::Normal, where_bound_origin: Some(origin), }; @@ -1201,8 +1091,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { hir_id: *hir_id, lifetimes: FxIndexMap::default(), s: self.scope, - next_early_index: self.next_early_index(), - opaque_type_parent: false, scope_type, where_bound_origin: None, }; @@ -1221,7 +1109,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { ) { debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref); - let next_early_index = self.next_early_index(); let (mut binders, scope_type) = self.poly_trait_ref_binder_info(); let initial_bound_vars = binders.len() as u32; @@ -1251,8 +1138,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { hir_id: trait_ref.trait_ref.hir_ref_id, lifetimes, s: self.scope, - next_early_index, - opaque_type_parent: false, scope_type, where_bound_origin: None, }; @@ -1354,30 +1239,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { /// ordering is not important there. fn visit_early_late( &mut self, - parent_id: Option, hir_id: hir::HirId, generics: &'tcx hir::Generics<'tcx>, walk: F, ) where F: for<'b, 'c> FnOnce(&'b mut LifetimeContext<'c, 'tcx>), { - // Find the start of nested early scopes, e.g., in methods. - let mut next_early_index = 0; - if let Some(parent_id) = parent_id { - let parent = self.tcx.hir().expect_item(parent_id); - if sub_items_have_self_param(&parent.kind) { - next_early_index += 1; // Self comes before lifetimes - } - match parent.kind { - hir::ItemKind::Trait(_, _, ref generics, ..) - | hir::ItemKind::Impl(hir::Impl { ref generics, .. }) => { - next_early_index += generics.params.len() as u32; - } - _ => {} - } - } - - let mut non_lifetime_count = 0; let mut named_late_bound_vars = 0; let lifetimes: FxIndexMap = generics .params @@ -1389,16 +1256,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { named_late_bound_vars += 1; Some(Region::late(late_bound_idx, self.tcx.hir(), param)) } else { - Some(Region::early(self.tcx.hir(), &mut next_early_index, param)) + Some(Region::early(self.tcx.hir(), param)) } } - GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { - non_lifetime_count += 1; - None - } + GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None, }) .collect(); - let next_early_index = next_early_index + non_lifetime_count; let binders: Vec<_> = generics .params @@ -1417,51 +1280,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let scope = Scope::Binder { hir_id, lifetimes, - next_early_index, s: self.scope, - opaque_type_parent: true, scope_type: BinderScopeType::Normal, where_bound_origin: None, }; self.with(scope, walk); } - fn next_early_index_helper(&self, only_opaque_type_parent: bool) -> u32 { - let mut scope = self.scope; - loop { - match *scope { - Scope::Root => return 0, - - Scope::Binder { next_early_index, opaque_type_parent, .. } - if (!only_opaque_type_parent || opaque_type_parent) => - { - return next_early_index; - } - - Scope::Binder { s, .. } - | Scope::Body { s, .. } - | Scope::Elision { s, .. } - | Scope::ObjectLifetimeDefault { s, .. } - | Scope::Supertrait { s, .. } - | Scope::TraitRefBoundary { s, .. } => scope = s, - } - } - } - - /// Returns the next index one would use for an early-bound-region - /// if extending the current scope. - fn next_early_index(&self) -> u32 { - self.next_early_index_helper(true) - } - - /// Returns the next index one would use for an `impl Trait` that - /// is being converted into an opaque type alias `impl Trait`. This will be the - /// next early index from the enclosing item, for the most - /// part. See the `opaque_type_parent` field for more info. - fn next_early_index_for_opaque_type(&self) -> u32 { - self.next_early_index_helper(false) - } - #[tracing::instrument(level = "debug", skip(self))] fn resolve_lifetime_ref( &mut self, diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index dd6831e44fd..bb2c533aa16 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -221,7 +221,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx.mk_region(ty::ReLateBound(debruijn, br)) } - Some(rl::Region::EarlyBound(_, def_id)) => { + Some(rl::Region::EarlyBound(def_id)) => { let name = tcx.hir().ty_param_name(def_id.expect_local()); let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local()); let generics = tcx.generics_of(item_def_id); @@ -2840,10 +2840,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); if !infer_replacements.is_empty() { - diag.multipart_suggestion(&format!( + diag.multipart_suggestion( + &format!( "try replacing `_` with the type{} in the corresponding trait method signature", rustc_errors::pluralize!(infer_replacements.len()), - ), infer_replacements, Applicability::MachineApplicable); + ), + infer_replacements, + Applicability::MachineApplicable, + ); } diag.emit(); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 116b1f16f7f..d8955a50cd2 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -216,7 +216,7 @@ impl<'tcx> Clean<'tcx, GenericBound> for ty::PolyTraitRef<'tcx> { fn clean_lifetime<'tcx>(lifetime: hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime { let def = cx.tcx.named_region(lifetime.hir_id); if let Some( - rl::Region::EarlyBound(_, node_id) + rl::Region::EarlyBound(node_id) | rl::Region::LateBound(_, _, node_id) | rl::Region::Free(_, node_id), ) = def -- cgit 1.4.1-3-g733a5 From 48bae9360feea931a0ef635ef1b69c61113dcd1a Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 27 Jul 2022 22:06:30 +0200 Subject: Use DefIdTree instead of open-coding it. --- compiler/rustc_resolve/src/late/lifetimes.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 01ada080b01..1892216dec0 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -1437,13 +1437,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // Figure out if this is a type/trait segment, // which requires object lifetime defaults. - let parent_def_id = |this: &mut Self, def_id: DefId| { - let def_key = this.tcx.def_key(def_id); - DefId { krate: def_id.krate, index: def_key.parent.expect("missing parent") } - }; let type_def_id = match res { - Res::Def(DefKind::AssocTy, def_id) if depth == 1 => Some(parent_def_id(self, def_id)), - Res::Def(DefKind::Variant, def_id) if depth == 0 => Some(parent_def_id(self, def_id)), + Res::Def(DefKind::AssocTy, def_id) if depth == 1 => Some(self.tcx.parent(def_id)), + Res::Def(DefKind::Variant, def_id) if depth == 0 => Some(self.tcx.parent(def_id)), Res::Def( DefKind::Struct | DefKind::Union -- cgit 1.4.1-3-g733a5 From a4240902529b75ed39995f506331eb532a6a0c51 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 27 Jul 2022 22:06:41 +0200 Subject: Simplify debugging. --- compiler/rustc_resolve/src/late/lifetimes.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 1892216dec0..4c894ccd53d 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -1409,17 +1409,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { ); } + #[tracing::instrument(level = "debug", skip(self))] fn visit_segment_args( &mut self, res: Res, depth: usize, generic_args: &'tcx hir::GenericArgs<'tcx>, ) { - debug!( - "visit_segment_args(res={:?}, depth={:?}, generic_args={:?})", - res, depth, generic_args, - ); - if generic_args.parenthesized { self.visit_fn_like_elision( generic_args.inputs(), @@ -1451,7 +1447,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { _ => None, }; - debug!("visit_segment_args: type_def_id={:?}", type_def_id); + debug!(?type_def_id); // Compute a vector of defaults, one for each type parameter, // per the rules given in RFCs 599 and 1156. Example: @@ -1516,7 +1512,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { .collect() }); - debug!("visit_segment_args: object_lifetime_defaults={:?}", object_lifetime_defaults); + debug!(?object_lifetime_defaults); let mut i = 0; for arg in generic_args.args { -- cgit 1.4.1-3-g733a5 From c95ff1d52bd3d8abec2e39b5b76426e22cc6d582 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 27 Jul 2022 22:22:39 +0200 Subject: Assert index sanity. --- compiler/rustc_resolve/src/late/lifetimes.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 4c894ccd53d..6ea976a5900 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -1486,6 +1486,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let map = &self.map; let generics = self.tcx.generics_of(def_id); + + // `type_def_id` points to an item, so there is nothing to inherit generics from. + debug_assert_eq!(generics.parent_count, 0); + let set_to_region = |set: ObjectLifetimeDefault| match set { ObjectLifetimeDefault::Empty => { if in_body { @@ -1496,8 +1500,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } ObjectLifetimeDefault::Static => Some(Region::Static), ObjectLifetimeDefault::Param(param_def_id) => { - let index = generics.param_def_id_to_index[¶m_def_id]; - generic_args.args.get(index as usize).and_then(|arg| match arg { + // This index can be used with `generic_args` since `parent_count == 0`. + let index = generics.param_def_id_to_index[¶m_def_id] as usize; + generic_args.args.get(index).and_then(|arg| match arg { GenericArg::Lifetime(lt) => map.defs.get(<.hir_id).copied(), _ => None, }) -- cgit 1.4.1-3-g733a5 From da90ec17e01d8360650a096ec53db5470839b3ab Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 27 Jul 2022 23:34:57 +0200 Subject: Bless incremental tests. --- src/test/incremental/hashes/enum_defs.rs | 8 ++++---- src/test/incremental/hashes/trait_defs.rs | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs index b466cfdd595..0f8898c389b 100644 --- a/src/test/incremental/hashes/enum_defs.rs +++ b/src/test/incremental/hashes/enum_defs.rs @@ -504,9 +504,9 @@ enum EnumAddLifetimeBoundToParameter<'a, T> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeBoundToParameter<'a, T: 'a> { Variant1(T), @@ -559,9 +559,9 @@ enum EnumAddLifetimeBoundToParameterWhere<'a, T> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeBoundToParameterWhere<'a, T> where T: 'a { Variant1(T), diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs index 1988f3f3541..c453eeceb77 100644 --- a/src/test/incremental/hashes/trait_defs.rs +++ b/src/test/incremental/hashes/trait_defs.rs @@ -1066,9 +1066,9 @@ trait TraitAddTraitBoundToTypeParameterOfTrait { } trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { } @@ -1144,9 +1144,9 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { } @@ -1201,9 +1201,9 @@ trait TraitAddTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { } @@ -1254,9 +1254,9 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a + 'b { } -- cgit 1.4.1-3-g733a5 From 1b87306b98eceb60873ee20e9542f855ec90809f Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Wed, 3 Aug 2022 18:12:21 -0700 Subject: Document that `RawWakerVTable` functions must be thread-safe. Also add some intra-doc links and more high-level explanation of how `Waker` is used, while I'm here. Context: https://internals.rust-lang.org/t/thread-safety-of-rawwakervtables/17126 --- library/core/src/task/wake.rs | 50 ++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 87d4a25afd5..1aeb30c667e 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -71,6 +71,12 @@ impl RawWaker { /// pointer of a properly constructed [`RawWaker`] object from inside the /// [`RawWaker`] implementation. Calling one of the contained functions using /// any other `data` pointer will cause undefined behavior. +/// +/// These functions must all be thread-safe (even though [`RawWaker`] is +/// \![Send] + \![Sync]) +/// because [`Waker`] is [Send] + [Sync], and thus wakers may be moved to +/// arbitrary threads or invoked by `&` reference. For example, this means that if the +/// `clone` and `drop` functions manage a reference count, they must do so atomically. #[stable(feature = "futures_api", since = "1.36.0")] #[derive(PartialEq, Copy, Clone, Debug)] pub struct RawWakerVTable { @@ -110,6 +116,12 @@ impl RawWakerVTable { /// Creates a new `RawWakerVTable` from the provided `clone`, `wake`, /// `wake_by_ref`, and `drop` functions. /// + /// These functions must all be thread-safe (even though [`RawWaker`] is + /// \![Send] + \![Sync]) + /// because [`Waker`] is [Send] + [Sync], and thus wakers may be moved to + /// arbitrary threads or invoked by `&` reference. For example, this means that if the + /// `clone` and `drop` functions manage a reference count, they must do so atomically. + /// /// # `clone` /// /// This function will be called when the [`RawWaker`] gets cloned, e.g. when @@ -157,9 +169,9 @@ impl RawWakerVTable { } } -/// The `Context` of an asynchronous task. +/// The context of an asynchronous task. /// -/// Currently, `Context` only serves to provide access to a `&Waker` +/// Currently, `Context` only serves to provide access to a [`&Waker`](Waker) /// which can be used to wake the current task. #[stable(feature = "futures_api", since = "1.36.0")] pub struct Context<'a> { @@ -172,7 +184,7 @@ pub struct Context<'a> { } impl<'a> Context<'a> { - /// Create a new `Context` from a `&Waker`. + /// Create a new [`Context`] from a [`&Waker`](Waker). #[stable(feature = "futures_api", since = "1.36.0")] #[must_use] #[inline] @@ -180,7 +192,7 @@ impl<'a> Context<'a> { Context { waker, _marker: PhantomData } } - /// Returns a reference to the `Waker` for the current task. + /// Returns a reference to the [`Waker`] for the current task. #[stable(feature = "futures_api", since = "1.36.0")] #[must_use] #[inline] @@ -202,7 +214,18 @@ impl fmt::Debug for Context<'_> { /// This handle encapsulates a [`RawWaker`] instance, which defines the /// executor-specific wakeup behavior. /// -/// Implements [`Clone`], [`Send`], and [`Sync`]. +/// The typical life of a [`Waker`] is that it is constructed by an executor, wrapped in a +/// [`Context`], then passed to [`Future::poll()`]. Then, if the future chooses to return +/// [`Poll::Pending`], it must also store the waker somehow and call [`Waker::wake()`] when +/// the future should be polled again. +/// +/// Implements [`Clone`], [`Send`], and [`Sync`]; therefore, a waker may be invoked +/// from any thread, including ones not in any way managed by the executor. For example, +/// this might be done to wake a future when a blocking function call completes on another +/// thread. +/// +/// [`Future::poll()`]: core::future::Future::poll +/// [`Poll::Pending`]: core::task::Poll::Pending #[repr(transparent)] #[stable(feature = "futures_api", since = "1.36.0")] pub struct Waker { @@ -219,18 +242,21 @@ unsafe impl Sync for Waker {} impl Waker { /// Wake up the task associated with this `Waker`. /// - /// As long as the runtime keeps running and the task is not finished, it is - /// guaranteed that each invocation of `wake` (or `wake_by_ref`) will be followed - /// by at least one `poll` of the task to which this `Waker` belongs. This makes + /// As long as the executor keeps running and the task is not finished, it is + /// guaranteed that each invocation of [`wake()`](Self::wake) (or + /// [`wake_by_ref()`](Self::wake_by_ref)) will be followed by at least one + /// [`poll()`] of the task to which this [`Waker`] belongs. This makes /// it possible to temporarily yield to other tasks while running potentially /// unbounded processing loops. /// /// Note that the above implies that multiple wake-ups may be coalesced into a - /// single `poll` invocation by the runtime. + /// single [`poll()`] invocation by the runtime. /// /// Also note that yielding to competing tasks is not guaranteed: it is the /// executor’s choice which task to run and the executor may choose to run the /// current task again. + /// + /// [`poll()`]: crate::future::Future::poll #[inline] #[stable(feature = "futures_api", since = "1.36.0")] pub fn wake(self) { @@ -250,8 +276,8 @@ impl Waker { /// Wake up the task associated with this `Waker` without consuming the `Waker`. /// - /// This is similar to `wake`, but may be slightly less efficient in the case - /// where an owned `Waker` is available. This method should be preferred to + /// This is similar to [`wake()`](Self::wake), but may be slightly less efficient in + /// the case where an owned `Waker` is available. This method should be preferred to /// calling `waker.clone().wake()`. #[inline] #[stable(feature = "futures_api", since = "1.36.0")] @@ -263,7 +289,7 @@ impl Waker { unsafe { (self.waker.vtable.wake_by_ref)(self.waker.data) } } - /// Returns `true` if this `Waker` and another `Waker` have awoken the same task. + /// Returns `true` if this `Waker` and another [`Waker`] would awake the same task. /// /// This function works on a best-effort basis, and may return false even /// when the `Waker`s would awaken the same task. However, if this function -- cgit 1.4.1-3-g733a5 From d4bcc4ae6dcd6c01f05edf1888d4696e61a40288 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Wed, 3 Aug 2022 22:07:50 -0700 Subject: Remove self-referential intra-doc links. --- library/core/src/task/wake.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 1aeb30c667e..60ecc9c0bdb 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -184,7 +184,7 @@ pub struct Context<'a> { } impl<'a> Context<'a> { - /// Create a new [`Context`] from a [`&Waker`](Waker). + /// Create a new `Context` from a [`&Waker`](Waker). #[stable(feature = "futures_api", since = "1.36.0")] #[must_use] #[inline] @@ -214,7 +214,7 @@ impl fmt::Debug for Context<'_> { /// This handle encapsulates a [`RawWaker`] instance, which defines the /// executor-specific wakeup behavior. /// -/// The typical life of a [`Waker`] is that it is constructed by an executor, wrapped in a +/// The typical life of a `Waker` is that it is constructed by an executor, wrapped in a /// [`Context`], then passed to [`Future::poll()`]. Then, if the future chooses to return /// [`Poll::Pending`], it must also store the waker somehow and call [`Waker::wake()`] when /// the future should be polled again. @@ -245,7 +245,7 @@ impl Waker { /// As long as the executor keeps running and the task is not finished, it is /// guaranteed that each invocation of [`wake()`](Self::wake) (or /// [`wake_by_ref()`](Self::wake_by_ref)) will be followed by at least one - /// [`poll()`] of the task to which this [`Waker`] belongs. This makes + /// [`poll()`] of the task to which this `Waker` belongs. This makes /// it possible to temporarily yield to other tasks while running potentially /// unbounded processing loops. /// @@ -289,7 +289,7 @@ impl Waker { unsafe { (self.waker.vtable.wake_by_ref)(self.waker.data) } } - /// Returns `true` if this `Waker` and another [`Waker`] would awake the same task. + /// Returns `true` if this `Waker` and another `Waker` would awake the same task. /// /// This function works on a best-effort basis, and may return false even /// when the `Waker`s would awaken the same task. However, if this function -- cgit 1.4.1-3-g733a5 From c1aae4d27902aaaa0d8e7d1a76d030b4fc90f329 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 13 May 2022 15:06:36 +0100 Subject: std::io: migrate ReadBuf to BorrowBuf/BorrowCursor Signed-off-by: Nick Cameron --- library/std/src/fs.rs | 10 +- library/std/src/io/buffered/bufreader.rs | 15 +- library/std/src/io/buffered/tests.rs | 32 ++-- library/std/src/io/copy.rs | 34 +++-- library/std/src/io/cursor.rs | 10 +- library/std/src/io/impls.rs | 16 +- library/std/src/io/mod.rs | 83 ++++++----- library/std/src/io/readbuf.rs | 243 +++++++++++++++---------------- library/std/src/io/readbuf/tests.rs | 172 +++++++--------------- library/std/src/io/tests.rs | 20 +-- library/std/src/io/util.rs | 14 +- library/std/src/io/util/tests.rs | 48 +++--- library/std/src/sys/unix/fd.rs | 11 +- library/std/src/sys/unix/fs.rs | 6 +- 14 files changed, 324 insertions(+), 390 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index c8e131b6ee1..d41f32b5b3f 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -13,7 +13,7 @@ mod tests; use crate::ffi::OsString; use crate::fmt; -use crate::io::{self, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, Write}; +use crate::io::{self, BorrowCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; use crate::path::{Path, PathBuf}; use crate::sys::fs as fs_imp; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; @@ -703,8 +703,8 @@ impl Read for File { self.inner.read_vectored(bufs) } - fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - self.inner.read_buf(buf) + fn read_buf(&mut self, cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + self.inner.read_buf(cursor) } #[inline] @@ -755,8 +755,8 @@ impl Read for &File { self.inner.read(buf) } - fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - self.inner.read_buf(buf) + fn read_buf(&mut self, cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + self.inner.read_buf(cursor) } fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index f7fbaa9c276..1f19ac11bf1 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -2,7 +2,8 @@ mod buffer; use crate::fmt; use crate::io::{ - self, BufRead, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, SizeHint, DEFAULT_BUF_SIZE, + self, BorrowBuf, BorrowCursor, BufRead, IoSliceMut, Read, Seek, SeekFrom, SizeHint, + DEFAULT_BUF_SIZE, }; use buffer::Buffer; @@ -266,21 +267,21 @@ impl Read for BufReader { Ok(nread) } - fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + fn read_buf(&mut self, mut cursor: BorrowCursor<'_, '_>) -> io::Result<()> { // If we don't have any buffered data and we're doing a massive read // (larger than our internal buffer), bypass our internal buffer // entirely. - if self.buf.pos() == self.buf.filled() && buf.remaining() >= self.capacity() { + if self.buf.pos() == self.buf.filled() && cursor.capacity() >= self.capacity() { self.discard_buffer(); - return self.inner.read_buf(buf); + return self.inner.read_buf(cursor); } - let prev = buf.filled_len(); + let prev = cursor.written(); let mut rem = self.fill_buf()?; - rem.read_buf(buf)?; + rem.read_buf(cursor.clone())?; - self.consume(buf.filled_len() - prev); //slice impl of read_buf known to never unfill buf + self.consume(cursor.written() - prev); //slice impl of read_buf known to never unfill buf Ok(()) } diff --git a/library/std/src/io/buffered/tests.rs b/library/std/src/io/buffered/tests.rs index fe45b132638..c93b69bf1f7 100644 --- a/library/std/src/io/buffered/tests.rs +++ b/library/std/src/io/buffered/tests.rs @@ -1,5 +1,5 @@ use crate::io::prelude::*; -use crate::io::{self, BufReader, BufWriter, ErrorKind, IoSlice, LineWriter, ReadBuf, SeekFrom}; +use crate::io::{self, BorrowBuf, BufReader, BufWriter, ErrorKind, IoSlice, LineWriter, SeekFrom}; use crate::mem::MaybeUninit; use crate::panic; use crate::sync::atomic::{AtomicUsize, Ordering}; @@ -61,48 +61,48 @@ fn test_buffered_reader_read_buf() { let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4]; let mut reader = BufReader::with_capacity(2, inner); - let mut buf = [MaybeUninit::uninit(); 3]; - let mut buf = ReadBuf::uninit(&mut buf); + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 3]; + let mut buf: BorrowBuf<'_> = buf.into(); - reader.read_buf(&mut buf).unwrap(); + reader.read_buf(buf.unfilled()).unwrap(); assert_eq!(buf.filled(), [5, 6, 7]); assert_eq!(reader.buffer(), []); - let mut buf = [MaybeUninit::uninit(); 2]; - let mut buf = ReadBuf::uninit(&mut buf); + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 2]; + let mut buf: BorrowBuf<'_> = buf.into(); - reader.read_buf(&mut buf).unwrap(); + reader.read_buf(buf.unfilled()).unwrap(); assert_eq!(buf.filled(), [0, 1]); assert_eq!(reader.buffer(), []); - let mut buf = [MaybeUninit::uninit(); 1]; - let mut buf = ReadBuf::uninit(&mut buf); + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 1]; + let mut buf: BorrowBuf<'_> = buf.into(); - reader.read_buf(&mut buf).unwrap(); + reader.read_buf(buf.unfilled()).unwrap(); assert_eq!(buf.filled(), [2]); assert_eq!(reader.buffer(), [3]); - let mut buf = [MaybeUninit::uninit(); 3]; - let mut buf = ReadBuf::uninit(&mut buf); + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 3]; + let mut buf: BorrowBuf<'_> = buf.into(); - reader.read_buf(&mut buf).unwrap(); + reader.read_buf(buf.unfilled()).unwrap(); assert_eq!(buf.filled(), [3]); assert_eq!(reader.buffer(), []); - reader.read_buf(&mut buf).unwrap(); + reader.read_buf(buf.unfilled()).unwrap(); assert_eq!(buf.filled(), [3, 4]); assert_eq!(reader.buffer(), []); buf.clear(); - reader.read_buf(&mut buf).unwrap(); + reader.read_buf(buf.unfilled()).unwrap(); - assert_eq!(buf.filled_len(), 0); + assert!(buf.filled().is_empty()); } #[test] diff --git a/library/std/src/io/copy.rs b/library/std/src/io/copy.rs index 1a10245e4a5..193bcd47467 100644 --- a/library/std/src/io/copy.rs +++ b/library/std/src/io/copy.rs @@ -1,4 +1,4 @@ -use super::{BufWriter, ErrorKind, Read, ReadBuf, Result, Write, DEFAULT_BUF_SIZE}; +use super::{BorrowBuf, BufWriter, ErrorKind, Read, Result, Write, DEFAULT_BUF_SIZE}; use crate::mem::MaybeUninit; /// Copies the entire contents of a reader into a writer. @@ -97,37 +97,39 @@ impl BufferedCopySpec for BufWriter { loop { let buf = writer.buffer_mut(); - let mut read_buf = ReadBuf::uninit(buf.spare_capacity_mut()); + let mut read_buf: BorrowBuf<'_> = buf.spare_capacity_mut().into(); - // SAFETY: init is either 0 or the initialized_len of the previous iteration unsafe { - read_buf.assume_init(init); + // SAFETY: init is either 0 or the init_len from the previous iteration. + read_buf.set_init(init); } if read_buf.capacity() >= DEFAULT_BUF_SIZE { - match reader.read_buf(&mut read_buf) { + let mut cursor = read_buf.unfilled(); + match reader.read_buf(cursor.clone()) { Ok(()) => { - let bytes_read = read_buf.filled_len(); + let bytes_read = cursor.written(); if bytes_read == 0 { return Ok(len); } - init = read_buf.initialized_len() - bytes_read; + init = read_buf.init_len() - bytes_read; + len += bytes_read as u64; - // SAFETY: ReadBuf guarantees all of its filled bytes are init + // SAFETY: BorrowBuf guarantees all of its filled bytes are init unsafe { buf.set_len(buf.len() + bytes_read) }; - len += bytes_read as u64; + // Read again if the buffer still has enough capacity, as BufWriter itself would do // This will occur if the reader returns short reads - continue; } - Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, + Err(ref e) if e.kind() == ErrorKind::Interrupted => {} Err(e) => return Err(e), } + } else { + writer.flush_buf()?; + init = 0; } - - writer.flush_buf()?; } } } @@ -136,13 +138,13 @@ fn stack_buffer_copy( reader: &mut R, writer: &mut W, ) -> Result { - let mut buf = [MaybeUninit::uninit(); DEFAULT_BUF_SIZE]; - let mut buf = ReadBuf::uninit(&mut buf); + let buf: &mut [_] = &mut [MaybeUninit::uninit(); DEFAULT_BUF_SIZE]; + let mut buf: BorrowBuf<'_> = buf.into(); let mut len = 0; loop { - match reader.read_buf(&mut buf) { + match reader.read_buf(buf.unfilled()) { Ok(()) => {} Err(e) if e.kind() == ErrorKind::Interrupted => continue, Err(e) => return Err(e), diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index f3fbfc44789..460b1504ffb 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -5,7 +5,7 @@ use crate::io::prelude::*; use crate::alloc::Allocator; use crate::cmp; -use crate::io::{self, ErrorKind, IoSlice, IoSliceMut, ReadBuf, SeekFrom}; +use crate::io::{self, BorrowCursor, ErrorKind, IoSlice, IoSliceMut, SeekFrom}; /// A `Cursor` wraps an in-memory buffer and provides it with a /// [`Seek`] implementation. @@ -323,12 +323,12 @@ where Ok(n) } - fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - let prev_filled = buf.filled_len(); + fn read_buf(&mut self, mut cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + let prev_written = cursor.written(); - Read::read_buf(&mut self.fill_buf()?, buf)?; + Read::read_buf(&mut self.fill_buf()?, cursor.clone())?; - self.pos += (buf.filled_len() - prev_filled) as u64; + self.pos += (cursor.written() - prev_written) as u64; Ok(()) } diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index 95072547302..eee5ab6ec10 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -6,7 +6,7 @@ use crate::cmp; use crate::collections::VecDeque; use crate::fmt; use crate::io::{ - self, BufRead, ErrorKind, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, Write, + self, BorrowCursor, BufRead, ErrorKind, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write, }; use crate::mem; @@ -21,8 +21,8 @@ impl Read for &mut R { } #[inline] - fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - (**self).read_buf(buf) + fn read_buf(&mut self, cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + (**self).read_buf(cursor) } #[inline] @@ -125,8 +125,8 @@ impl Read for Box { } #[inline] - fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - (**self).read_buf(buf) + fn read_buf(&mut self, cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + (**self).read_buf(cursor) } #[inline] @@ -249,11 +249,11 @@ impl Read for &[u8] { } #[inline] - fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - let amt = cmp::min(buf.remaining(), self.len()); + fn read_buf(&mut self, mut cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + let amt = cmp::min(cursor.capacity(), self.len()); let (a, b) = self.split_at(amt); - buf.append(a); + cursor.append(a); *self = b; Ok(()) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 96addbd1a05..b3218b2831d 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -278,7 +278,7 @@ pub use self::{ }; #[unstable(feature = "read_buf", issue = "78485")] -pub use self::readbuf::ReadBuf; +pub use self::readbuf::{BorrowBuf, BorrowCursor}; pub(crate) use error::const_io_error; mod buffered; @@ -362,29 +362,30 @@ pub(crate) fn default_read_to_end(r: &mut R, buf: &mut Vec buf.reserve(32); // buf is full, need more space } - let mut read_buf = ReadBuf::uninit(buf.spare_capacity_mut()); + let mut read_buf: BorrowBuf<'_> = buf.spare_capacity_mut().into(); // SAFETY: These bytes were initialized but not filled in the previous loop unsafe { - read_buf.assume_init(initialized); + read_buf.set_init(initialized); } - match r.read_buf(&mut read_buf) { + let mut cursor = read_buf.unfilled(); + match r.read_buf(cursor.clone()) { Ok(()) => {} Err(e) if e.kind() == ErrorKind::Interrupted => continue, Err(e) => return Err(e), } - if read_buf.filled_len() == 0 { + if cursor.written() == 0 { return Ok(buf.len() - start_len); } // store how much was initialized but not filled - initialized = read_buf.initialized_len() - read_buf.filled_len(); - let new_len = read_buf.filled_len() + buf.len(); + initialized = cursor.init_ref().len(); - // SAFETY: ReadBuf's invariants mean this much memory is init + // SAFETY: BorrowBuf's invariants mean this much memory is initialized. unsafe { + let new_len = read_buf.filled().len() + buf.len(); buf.set_len(new_len); } @@ -461,12 +462,15 @@ pub(crate) fn default_read_exact(this: &mut R, mut buf: &mut [ } } -pub(crate) fn default_read_buf(read: F, buf: &mut ReadBuf<'_>) -> Result<()> +pub(crate) fn default_read_buf(read: F, mut cursor: BorrowCursor<'_, '_>) -> Result<()> where F: FnOnce(&mut [u8]) -> Result, { - let n = read(buf.initialize_unfilled())?; - buf.add_filled(n); + let n = read(cursor.ensure_init().init_mut())?; + unsafe { + // SAFETY: we initialised using `ensure_init` so there is no uninit data to advance to. + cursor.advance(n); + } Ok(()) } @@ -801,32 +805,33 @@ pub trait Read { default_read_exact(self, buf) } + // TODO naming, if should the method be read_cursor? Or should we change the names of the data structures? /// Pull some bytes from this source into the specified buffer. /// - /// This is equivalent to the [`read`](Read::read) method, except that it is passed a [`ReadBuf`] rather than `[u8]` to allow use + /// This is equivalent to the [`read`](Read::read) method, except that it is passed a [`BorrowCursor`] rather than `[u8]` to allow use /// with uninitialized buffers. The new data will be appended to any existing contents of `buf`. /// /// The default implementation delegates to `read`. #[unstable(feature = "read_buf", issue = "78485")] - fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> Result<()> { + fn read_buf(&mut self, buf: BorrowCursor<'_, '_>) -> Result<()> { default_read_buf(|b| self.read(b), buf) } - /// Read the exact number of bytes required to fill `buf`. + /// Read the exact number of bytes required to fill `cursor`. /// - /// This is equivalent to the [`read_exact`](Read::read_exact) method, except that it is passed a [`ReadBuf`] rather than `[u8]` to + /// This is equivalent to the [`read_exact`](Read::read_exact) method, except that it is passed a [`BorrowCursor`] rather than `[u8]` to /// allow use with uninitialized buffers. #[unstable(feature = "read_buf", issue = "78485")] - fn read_buf_exact(&mut self, buf: &mut ReadBuf<'_>) -> Result<()> { - while buf.remaining() > 0 { - let prev_filled = buf.filled().len(); - match self.read_buf(buf) { + fn read_buf_exact(&mut self, mut cursor: BorrowCursor<'_, '_>) -> Result<()> { + while cursor.capacity() > 0 { + let prev_written = cursor.written(); + match self.read_buf(cursor.clone()) { Ok(()) => {} Err(e) if e.kind() == ErrorKind::Interrupted => continue, Err(e) => return Err(e), } - if buf.filled().len() == prev_filled { + if cursor.written() == prev_written { return Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill buffer")); } } @@ -2582,50 +2587,48 @@ impl Read for Take { Ok(n) } - fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> Result<()> { + fn read_buf(&mut self, mut buf: BorrowCursor<'_, '_>) -> Result<()> { // Don't call into inner reader at all at EOF because it may still block if self.limit == 0 { return Ok(()); } - let prev_filled = buf.filled_len(); - - if self.limit <= buf.remaining() as u64 { + if self.limit <= buf.capacity() as u64 { // if we just use an as cast to convert, limit may wrap around on a 32 bit target let limit = cmp::min(self.limit, usize::MAX as u64) as usize; - let extra_init = cmp::min(limit as usize, buf.initialized_len() - buf.filled_len()); + let extra_init = cmp::min(limit as usize, buf.init_ref().len()); // SAFETY: no uninit data is written to ibuf - let ibuf = unsafe { &mut buf.unfilled_mut()[..limit] }; + let ibuf = unsafe { &mut buf.as_mut()[..limit] }; - let mut sliced_buf = ReadBuf::uninit(ibuf); + let mut sliced_buf: BorrowBuf<'_> = ibuf.into(); // SAFETY: extra_init bytes of ibuf are known to be initialized unsafe { - sliced_buf.assume_init(extra_init); + sliced_buf.set_init(extra_init); } - self.inner.read_buf(&mut sliced_buf)?; + let mut cursor = sliced_buf.unfilled(); + self.inner.read_buf(cursor.clone())?; - let new_init = sliced_buf.initialized_len(); - let filled = sliced_buf.filled_len(); + let new_init = cursor.init_ref().len(); + let filled = sliced_buf.len(); - // sliced_buf / ibuf must drop here + // cursor / sliced_buf / ibuf must drop here - // SAFETY: new_init bytes of buf's unfilled buffer have been initialized unsafe { - buf.assume_init(new_init); + // SAFETY: filled bytes have been filled and therefore initialized + buf.advance(filled); + // SAFETY: new_init bytes of buf's unfilled buffer have been initialized + buf.set_init(new_init); } - buf.add_filled(filled); - self.limit -= filled as u64; } else { - self.inner.read_buf(buf)?; - - //inner may unfill - self.limit -= buf.filled_len().saturating_sub(prev_filled) as u64; + let written = buf.written(); + self.inner.read_buf(buf.clone())?; + self.limit -= (buf.written() - written) as u64; } Ok(()) diff --git a/library/std/src/io/readbuf.rs b/library/std/src/io/readbuf.rs index 78d1113f837..4578433b22a 100644 --- a/library/std/src/io/readbuf.rs +++ b/library/std/src/io/readbuf.rs @@ -7,6 +7,7 @@ use crate::cmp; use crate::fmt::{self, Debug, Formatter}; use crate::mem::MaybeUninit; +// TODO docs /// A wrapper around a byte buffer that is incrementally filled and initialized. /// /// This type is a sort of "double cursor". It tracks three regions in the buffer: a region at the beginning of the @@ -20,50 +21,66 @@ use crate::mem::MaybeUninit; /// [ filled | unfilled ] /// [ initialized | uninitialized ] /// ``` -pub struct ReadBuf<'a> { +pub struct BorrowBuf<'a> { buf: &'a mut [MaybeUninit], filled: usize, initialized: usize, } -impl Debug for ReadBuf<'_> { +impl Debug for BorrowBuf<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("ReadBuf") - .field("init", &self.initialized()) + .field("init", &self.initialized) .field("filled", &self.filled) .field("capacity", &self.capacity()) .finish() } } -impl<'a> ReadBuf<'a> { - /// Creates a new `ReadBuf` from a fully initialized buffer. +/// Creates a new `BorrowBuf` from a fully initialized slice. +impl<'a> From<&'a mut [u8]> for BorrowBuf<'a> { #[inline] - pub fn new(buf: &'a mut [u8]) -> ReadBuf<'a> { - let len = buf.len(); + fn from(slice: &'a mut [u8]) -> BorrowBuf<'a> { + let len = slice.len(); - ReadBuf { - //SAFETY: initialized data never becoming uninitialized is an invariant of ReadBuf - buf: unsafe { (buf as *mut [u8]).as_uninit_slice_mut().unwrap() }, + BorrowBuf { + //SAFETY: initialized data never becoming uninitialized is an invariant of BorrowBuf + buf: unsafe { (slice as *mut [u8]).as_uninit_slice_mut().unwrap() }, filled: 0, initialized: len, } } +} - /// Creates a new `ReadBuf` from a fully uninitialized buffer. - /// - /// Use `assume_init` if part of the buffer is known to be already initialized. +/// Creates a new `BorrowBuf` from a fully uninitialized buffer. +/// +/// Use `set_init` if part of the buffer is known to be already initialized. +impl<'a> From<&'a mut [MaybeUninit]> for BorrowBuf<'a> { #[inline] - pub fn uninit(buf: &'a mut [MaybeUninit]) -> ReadBuf<'a> { - ReadBuf { buf, filled: 0, initialized: 0 } + fn from(buf: &'a mut [MaybeUninit]) -> BorrowBuf<'a> { + BorrowBuf { buf, filled: 0, initialized: 0 } } +} +impl<'a> BorrowBuf<'a> { /// Returns the total capacity of the buffer. #[inline] pub fn capacity(&self) -> usize { self.buf.len() } + /// Returns the length of the filled part of the buffer. + #[inline] + pub fn len(&self) -> usize { + self.filled + } + + /// Returns the length of the initialized part of the buffer. + #[inline] + pub fn init_len(&self) -> usize { + self.initialized + } + /// Returns a shared reference to the filled portion of the buffer. #[inline] pub fn filled(&self) -> &[u8] { @@ -71,179 +88,157 @@ impl<'a> ReadBuf<'a> { unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[0..self.filled]) } } - /// Returns a mutable reference to the filled portion of the buffer. + /// Returns a cursor over the unfilled part of the buffer. #[inline] - pub fn filled_mut(&mut self) -> &mut [u8] { - //SAFETY: We only slice the filled part of the buffer, which is always valid - unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[0..self.filled]) } + pub fn unfilled<'b>(&'b mut self) -> BorrowCursor<'a, 'b> { + BorrowCursor { start: self.filled, buf: self } } - /// Returns a shared reference to the initialized portion of the buffer. + /// Clears the buffer, resetting the filled region to empty. /// - /// This includes the filled portion. + /// The number of initialized bytes is not changed, and the contents of the buffer are not modified. #[inline] - pub fn initialized(&self) -> &[u8] { - //SAFETY: We only slice the initialized part of the buffer, which is always valid - unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[0..self.initialized]) } + pub fn clear(&mut self) -> &mut Self { + self.filled = 0; + self } - /// Returns a mutable reference to the initialized portion of the buffer. + /// Asserts that the first `n` bytes of the buffer are initialized. /// - /// This includes the filled portion. - #[inline] - pub fn initialized_mut(&mut self) -> &mut [u8] { - //SAFETY: We only slice the initialized part of the buffer, which is always valid - unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[0..self.initialized]) } - } - - /// Returns a mutable reference to the unfilled part of the buffer without ensuring that it has been fully - /// initialized. + /// `BorrowBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer + /// bytes than are already known to be initialized. /// /// # Safety /// - /// The caller must not de-initialize portions of the buffer that have already been initialized. + /// The caller must ensure that the first `n` unfilled bytes of the buffer have already been initialized. #[inline] - pub unsafe fn unfilled_mut(&mut self) -> &mut [MaybeUninit] { - &mut self.buf[self.filled..] + pub unsafe fn set_init(&mut self, n: usize) -> &mut Self { + self.initialized = cmp::max(self.initialized, n); + self } +} - /// Returns a mutable reference to the uninitialized part of the buffer. - /// - /// It is safe to uninitialize any of these bytes. +/// A cursor view of a [`BorrowBuf`](BorrowBuf). +/// +/// Provides mutable access to the unfilled portion (both initialised and uninitialised data) from +/// the buffer. +#[derive(Debug)] +pub struct BorrowCursor<'a, 'b> { + buf: &'b mut BorrowBuf<'a>, + start: usize, +} + +impl<'a, 'b> BorrowCursor<'a, 'b> { + /// Clone this cursor. #[inline] - pub fn uninitialized_mut(&mut self) -> &mut [MaybeUninit] { - &mut self.buf[self.initialized..] + pub fn clone<'c>(&'c mut self) -> BorrowCursor<'a, 'c> { + BorrowCursor { buf: self.buf, start: self.start } } - /// Returns a mutable reference to the unfilled part of the buffer, ensuring it is fully initialized. - /// - /// Since `ReadBuf` tracks the region of the buffer that has been initialized, this is effectively "free" after - /// the first use. + /// Returns the available space in the cursor. #[inline] - pub fn initialize_unfilled(&mut self) -> &mut [u8] { - // should optimize out the assertion - self.initialize_unfilled_to(self.remaining()) + pub fn capacity(&self) -> usize { + self.buf.capacity() - self.buf.filled } - /// Returns a mutable reference to the first `n` bytes of the unfilled part of the buffer, ensuring it is - /// fully initialized. - /// - /// # Panics - /// - /// Panics if `self.remaining()` is less than `n`. + /// Returns the number of bytes written to this cursor. + // TODO check for reuse uses #[inline] - pub fn initialize_unfilled_to(&mut self, n: usize) -> &mut [u8] { - assert!(self.remaining() >= n); - - let extra_init = self.initialized - self.filled; - // If we don't have enough initialized, do zeroing - if n > extra_init { - let uninit = n - extra_init; - let unfilled = &mut self.uninitialized_mut()[0..uninit]; - - for byte in unfilled.iter_mut() { - byte.write(0); - } + pub fn written(&self) -> usize { + self.buf.filled - self.start + } - // SAFETY: we just initialized uninit bytes, and the previous bytes were already init - unsafe { - self.assume_init(n); - } + /// Returns a shared reference to the initialized portion of the buffer. + #[inline] + pub fn init_ref(&self) -> &[u8] { + //SAFETY: We only slice the initialized part of the buffer, which is always valid + unsafe { + MaybeUninit::slice_assume_init_ref(&self.buf.buf[self.buf.filled..self.buf.initialized]) } - - let filled = self.filled; - - &mut self.initialized_mut()[filled..filled + n] } - /// Returns the number of bytes at the end of the slice that have not yet been filled. + /// Returns a mutable reference to the initialized portion of the buffer. #[inline] - pub fn remaining(&self) -> usize { - self.capacity() - self.filled + pub fn init_mut(&mut self) -> &mut [u8] { + //SAFETY: We only slice the initialized part of the buffer, which is always valid + unsafe { + MaybeUninit::slice_assume_init_mut( + &mut self.buf.buf[self.buf.filled..self.buf.initialized], + ) + } } - /// Clears the buffer, resetting the filled region to empty. + /// Returns a mutable reference to the uninitialized part of the buffer. /// - /// The number of initialized bytes is not changed, and the contents of the buffer are not modified. + /// It is safe to uninitialize any of these bytes. #[inline] - pub fn clear(&mut self) -> &mut Self { - self.set_filled(0) // The assertion in `set_filled` is optimized out + pub fn uninit_mut(&mut self) -> &mut [MaybeUninit] { + &mut self.buf.buf[self.buf.initialized..] + } + + /// A view of the cursor as a mutable slice of `MaybeUninit`. + #[inline] + pub unsafe fn as_mut(&mut self) -> &mut [MaybeUninit] { + &mut self.buf.buf[self.buf.filled..] } /// Increases the size of the filled region of the buffer. /// - /// The number of initialized bytes is not changed. - /// - /// # Panics + /// # Safety /// - /// Panics if the filled region of the buffer would become larger than the initialized region. + /// The caller must ensure that the first `n` elements of the cursor have been properly + /// initialised. #[inline] - pub fn add_filled(&mut self, n: usize) -> &mut Self { - self.set_filled(self.filled + n) + pub unsafe fn advance(&mut self, n: usize) -> &mut Self { + self.buf.filled += n; + self.buf.initialized = cmp::max(self.buf.initialized, self.buf.filled); + self } - /// Sets the size of the filled region of the buffer. - /// - /// The number of initialized bytes is not changed. - /// - /// Note that this can be used to *shrink* the filled region of the buffer in addition to growing it (for - /// example, by a `Read` implementation that compresses data in-place). - /// - /// # Panics - /// - /// Panics if the filled region of the buffer would become larger than the initialized region. + /// Initialised all bytes in the cursor. #[inline] - pub fn set_filled(&mut self, n: usize) -> &mut Self { - assert!(n <= self.initialized); + pub fn ensure_init(&mut self) -> &mut Self { + for byte in self.uninit_mut() { + byte.write(0); + } + self.buf.initialized = self.buf.capacity(); - self.filled = n; self } - /// Asserts that the first `n` unfilled bytes of the buffer are initialized. + /// Asserts that the first `n` unfilled bytes of the cursor are initialized. /// - /// `ReadBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer + /// `BorrowBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer /// bytes than are already known to be initialized. /// /// # Safety /// - /// The caller must ensure that the first `n` unfilled bytes of the buffer have already been initialized. + /// The caller must ensure that the first `n` bytes of the buffer have already been initialized. #[inline] - pub unsafe fn assume_init(&mut self, n: usize) -> &mut Self { - self.initialized = cmp::max(self.initialized, self.filled + n); + pub unsafe fn set_init(&mut self, n: usize) -> &mut Self { + self.buf.initialized = cmp::max(self.buf.initialized, self.buf.filled + n); self } - /// Appends data to the buffer, advancing the written position and possibly also the initialized position. + /// Appends data to the cursor, advancing the position within its buffer. /// /// # Panics /// - /// Panics if `self.remaining()` is less than `buf.len()`. + /// Panics if `self.capacity()` is less than `buf.len()`. #[inline] pub fn append(&mut self, buf: &[u8]) { - assert!(self.remaining() >= buf.len()); + assert!(self.capacity() >= buf.len()); // SAFETY: we do not de-initialize any of the elements of the slice unsafe { - MaybeUninit::write_slice(&mut self.unfilled_mut()[..buf.len()], buf); + MaybeUninit::write_slice(&mut self.as_mut()[..buf.len()], buf); } // SAFETY: We just added the entire contents of buf to the filled section. unsafe { - self.assume_init(buf.len()); - } - self.add_filled(buf.len()); - } - - /// Returns the amount of bytes that have been filled. - #[inline] - pub fn filled_len(&self) -> usize { - self.filled - } - /// Returns the amount of bytes that have been initialized. - #[inline] - pub fn initialized_len(&self) -> usize { - self.initialized + self.set_init(buf.len()); + } + self.buf.filled += buf.len(); } } diff --git a/library/std/src/io/readbuf/tests.rs b/library/std/src/io/readbuf/tests.rs index 3b7a5a56d22..584e5de982e 100644 --- a/library/std/src/io/readbuf/tests.rs +++ b/library/std/src/io/readbuf/tests.rs @@ -1,181 +1,117 @@ -use super::ReadBuf; +use super::BorrowBuf; use crate::mem::MaybeUninit; -/// Test that ReadBuf has the correct numbers when created with new +/// Test that BorrowBuf has the correct numbers when created with new #[test] fn new() { - let mut buf = [0; 16]; - let rbuf = ReadBuf::new(&mut buf); + let buf: &mut [_] = &mut [0; 16]; + let mut rbuf: BorrowBuf<'_> = buf.into(); - assert_eq!(rbuf.filled_len(), 0); - assert_eq!(rbuf.initialized_len(), 16); + assert_eq!(rbuf.filled().len(), 0); + assert_eq!(rbuf.init_len(), 16); assert_eq!(rbuf.capacity(), 16); - assert_eq!(rbuf.remaining(), 16); + assert_eq!(rbuf.unfilled().capacity(), 16); } -/// Test that ReadBuf has the correct numbers when created with uninit +/// Test that BorrowBuf has the correct numbers when created with uninit #[test] fn uninit() { - let mut buf = [MaybeUninit::uninit(); 16]; - let rbuf = ReadBuf::uninit(&mut buf); + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16]; + let mut rbuf: BorrowBuf<'_> = buf.into(); - assert_eq!(rbuf.filled_len(), 0); - assert_eq!(rbuf.initialized_len(), 0); + assert_eq!(rbuf.filled().len(), 0); + assert_eq!(rbuf.init_len(), 0); assert_eq!(rbuf.capacity(), 16); - assert_eq!(rbuf.remaining(), 16); + assert_eq!(rbuf.unfilled().capacity(), 16); } #[test] fn initialize_unfilled() { - let mut buf = [MaybeUninit::uninit(); 16]; - let mut rbuf = ReadBuf::uninit(&mut buf); + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16]; + let mut rbuf: BorrowBuf<'_> = buf.into(); - rbuf.initialize_unfilled(); + rbuf.unfilled().ensure_init(); - assert_eq!(rbuf.initialized_len(), 16); -} - -#[test] -fn initialize_unfilled_to() { - let mut buf = [MaybeUninit::uninit(); 16]; - let mut rbuf = ReadBuf::uninit(&mut buf); - - rbuf.initialize_unfilled_to(8); - - assert_eq!(rbuf.initialized_len(), 8); - - rbuf.initialize_unfilled_to(4); - - assert_eq!(rbuf.initialized_len(), 8); - - rbuf.set_filled(8); - - rbuf.initialize_unfilled_to(6); - - assert_eq!(rbuf.initialized_len(), 14); - - rbuf.initialize_unfilled_to(8); - - assert_eq!(rbuf.initialized_len(), 16); + assert_eq!(rbuf.init_len(), 16); } #[test] fn add_filled() { - let mut buf = [0; 16]; - let mut rbuf = ReadBuf::new(&mut buf); - - rbuf.add_filled(1); - - assert_eq!(rbuf.filled_len(), 1); - assert_eq!(rbuf.remaining(), 15); -} + let buf: &mut [_] = &mut [0; 16]; + let mut rbuf: BorrowBuf<'_> = buf.into(); -#[test] -#[should_panic] -fn add_filled_panic() { - let mut buf = [MaybeUninit::uninit(); 16]; - let mut rbuf = ReadBuf::uninit(&mut buf); - - rbuf.add_filled(1); -} - -#[test] -fn set_filled() { - let mut buf = [0; 16]; - let mut rbuf = ReadBuf::new(&mut buf); - - rbuf.set_filled(16); - - assert_eq!(rbuf.filled_len(), 16); - assert_eq!(rbuf.remaining(), 0); - - rbuf.set_filled(6); - - assert_eq!(rbuf.filled_len(), 6); - assert_eq!(rbuf.remaining(), 10); -} - -#[test] -#[should_panic] -fn set_filled_panic() { - let mut buf = [MaybeUninit::uninit(); 16]; - let mut rbuf = ReadBuf::uninit(&mut buf); + unsafe { + rbuf.unfilled().advance(1); + } - rbuf.set_filled(16); + assert_eq!(rbuf.filled().len(), 1); + assert_eq!(rbuf.unfilled().capacity(), 15); } #[test] fn clear() { - let mut buf = [255; 16]; - let mut rbuf = ReadBuf::new(&mut buf); + let buf: &mut [_] = &mut [255; 16]; + let mut rbuf: BorrowBuf<'_> = buf.into(); - rbuf.set_filled(16); + unsafe { + rbuf.unfilled().advance(16); + } - assert_eq!(rbuf.filled_len(), 16); - assert_eq!(rbuf.remaining(), 0); + assert_eq!(rbuf.filled().len(), 16); + assert_eq!(rbuf.unfilled().capacity(), 0); rbuf.clear(); - assert_eq!(rbuf.filled_len(), 0); - assert_eq!(rbuf.remaining(), 16); + assert_eq!(rbuf.filled().len(), 0); + assert_eq!(rbuf.unfilled().capacity(), 16); - assert_eq!(rbuf.initialized(), [255; 16]); + assert_eq!(rbuf.unfilled().init_ref(), [255; 16]); } #[test] -fn assume_init() { - let mut buf = [MaybeUninit::uninit(); 16]; - let mut rbuf = ReadBuf::uninit(&mut buf); +fn set_init() { + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16]; + let mut rbuf: BorrowBuf<'_> = buf.into(); unsafe { - rbuf.assume_init(8); + rbuf.set_init(8); } - assert_eq!(rbuf.initialized_len(), 8); + assert_eq!(rbuf.init_len(), 8); - rbuf.add_filled(4); + unsafe { + rbuf.unfilled().advance(4); + } unsafe { - rbuf.assume_init(2); + rbuf.set_init(2); } - assert_eq!(rbuf.initialized_len(), 8); + assert_eq!(rbuf.init_len(), 8); unsafe { - rbuf.assume_init(8); + rbuf.set_init(8); } - assert_eq!(rbuf.initialized_len(), 12); + assert_eq!(rbuf.init_len(), 8); } #[test] fn append() { - let mut buf = [MaybeUninit::new(255); 16]; - let mut rbuf = ReadBuf::uninit(&mut buf); + let buf: &mut [_] = &mut [MaybeUninit::new(255); 16]; + let mut rbuf: BorrowBuf<'_> = buf.into(); - rbuf.append(&[0; 8]); + rbuf.unfilled().append(&[0; 8]); - assert_eq!(rbuf.initialized_len(), 8); - assert_eq!(rbuf.filled_len(), 8); + assert_eq!(rbuf.init_len(), 8); + assert_eq!(rbuf.filled().len(), 8); assert_eq!(rbuf.filled(), [0; 8]); rbuf.clear(); - rbuf.append(&[1; 16]); + rbuf.unfilled().append(&[1; 16]); - assert_eq!(rbuf.initialized_len(), 16); - assert_eq!(rbuf.filled_len(), 16); + assert_eq!(rbuf.init_len(), 16); + assert_eq!(rbuf.filled().len(), 16); assert_eq!(rbuf.filled(), [1; 16]); } - -#[test] -fn filled_mut() { - let mut buf = [0; 16]; - let mut rbuf = ReadBuf::new(&mut buf); - - rbuf.add_filled(8); - - let filled = rbuf.filled().to_vec(); - - assert_eq!(&*filled, &*rbuf.filled_mut()); -} diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index f357f33ec52..a1322a18565 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -1,4 +1,4 @@ -use super::{repeat, Cursor, ReadBuf, SeekFrom}; +use super::{repeat, BorrowBuf, Cursor, SeekFrom}; use crate::cmp::{self, min}; use crate::io::{self, IoSlice, IoSliceMut}; use crate::io::{BufRead, BufReader, Read, Seek, Write}; @@ -159,24 +159,24 @@ fn read_exact_slice() { #[test] fn read_buf_exact() { - let mut buf = [0; 4]; - let mut buf = ReadBuf::new(&mut buf); + let buf: &mut [_] = &mut [0; 4]; + let mut buf: BorrowBuf<'_> = buf.into(); let mut c = Cursor::new(&b""[..]); - assert_eq!(c.read_buf_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof); + assert_eq!(c.read_buf_exact(buf.unfilled()).unwrap_err().kind(), io::ErrorKind::UnexpectedEof); let mut c = Cursor::new(&b"123456789"[..]); - c.read_buf_exact(&mut buf).unwrap(); + c.read_buf_exact(buf.unfilled()).unwrap(); assert_eq!(buf.filled(), b"1234"); buf.clear(); - c.read_buf_exact(&mut buf).unwrap(); + c.read_buf_exact(buf.unfilled()).unwrap(); assert_eq!(buf.filled(), b"5678"); buf.clear(); - assert_eq!(c.read_buf_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof); + assert_eq!(c.read_buf_exact(buf.unfilled()).unwrap_err().kind(), io::ErrorKind::UnexpectedEof); } #[test] @@ -614,10 +614,10 @@ fn bench_take_read(b: &mut test::Bencher) { #[bench] fn bench_take_read_buf(b: &mut test::Bencher) { b.iter(|| { - let mut buf = [MaybeUninit::uninit(); 64]; + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 64]; - let mut rbuf = ReadBuf::uninit(&mut buf); + let mut buf: BorrowBuf<'_> = buf.into(); - [255; 128].take(64).read_buf(&mut rbuf).unwrap(); + [255; 128].take(64).read_buf(buf.unfilled()).unwrap(); }); } diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index c1300cd67c0..5149926fd51 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -5,7 +5,7 @@ mod tests; use crate::fmt; use crate::io::{ - self, BufRead, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, SizeHint, Write, + self, BorrowCursor, BufRead, IoSlice, IoSliceMut, Read, Seek, SeekFrom, SizeHint, Write, }; /// A reader which is always at EOF. @@ -47,7 +47,7 @@ impl Read for Empty { } #[inline] - fn read_buf(&mut self, _buf: &mut ReadBuf<'_>) -> io::Result<()> { + fn read_buf(&mut self, _cursor: BorrowCursor<'_, '_>) -> io::Result<()> { Ok(()) } } @@ -130,21 +130,19 @@ impl Read for Repeat { Ok(buf.len()) } - fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + fn read_buf(&mut self, mut buf: BorrowCursor<'_, '_>) -> io::Result<()> { // SAFETY: No uninit bytes are being written - for slot in unsafe { buf.unfilled_mut() } { + for slot in unsafe { buf.as_mut() } { slot.write(self.byte); } - let remaining = buf.remaining(); + let remaining = buf.capacity(); // SAFETY: the entire unfilled portion of buf has been initialized unsafe { - buf.assume_init(remaining); + buf.advance(remaining); } - buf.add_filled(remaining); - Ok(()) } diff --git a/library/std/src/io/util/tests.rs b/library/std/src/io/util/tests.rs index 08972a59a83..025173c3f44 100644 --- a/library/std/src/io/util/tests.rs +++ b/library/std/src/io/util/tests.rs @@ -1,7 +1,7 @@ use crate::cmp::{max, min}; use crate::io::prelude::*; use crate::io::{ - copy, empty, repeat, sink, BufWriter, Empty, ReadBuf, Repeat, Result, SeekFrom, Sink, + copy, empty, repeat, sink, BorrowBuf, BufWriter, Empty, Repeat, Result, SeekFrom, Sink, DEFAULT_BUF_SIZE, }; @@ -79,29 +79,29 @@ fn empty_reads() { assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0); assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0); - let mut buf = []; - let mut buf = ReadBuf::uninit(&mut buf); - e.read_buf(&mut buf).unwrap(); - assert_eq!(buf.filled_len(), 0); - assert_eq!(buf.initialized_len(), 0); - - let mut buf = [MaybeUninit::uninit()]; - let mut buf = ReadBuf::uninit(&mut buf); - e.read_buf(&mut buf).unwrap(); - assert_eq!(buf.filled_len(), 0); - assert_eq!(buf.initialized_len(), 0); - - let mut buf = [MaybeUninit::uninit(); 1024]; - let mut buf = ReadBuf::uninit(&mut buf); - e.read_buf(&mut buf).unwrap(); - assert_eq!(buf.filled_len(), 0); - assert_eq!(buf.initialized_len(), 0); - - let mut buf = [MaybeUninit::uninit(); 1024]; - let mut buf = ReadBuf::uninit(&mut buf); - e.by_ref().read_buf(&mut buf).unwrap(); - assert_eq!(buf.filled_len(), 0); - assert_eq!(buf.initialized_len(), 0); + let buf: &mut [MaybeUninit<_>] = &mut []; + let mut buf: BorrowBuf<'_> = buf.into(); + e.read_buf(buf.unfilled()).unwrap(); + assert_eq!(buf.len(), 0); + assert_eq!(buf.init_len(), 0); + + let buf: &mut [_] = &mut [MaybeUninit::uninit()]; + let mut buf: BorrowBuf<'_> = buf.into(); + e.read_buf(buf.unfilled()).unwrap(); + assert_eq!(buf.len(), 0); + assert_eq!(buf.init_len(), 0); + + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 1024]; + let mut buf: BorrowBuf<'_> = buf.into(); + e.read_buf(buf.unfilled()).unwrap(); + assert_eq!(buf.len(), 0); + assert_eq!(buf.init_len(), 0); + + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 1024]; + let mut buf: BorrowBuf<'_> = buf.into(); + e.by_ref().read_buf(buf.unfilled()).unwrap(); + assert_eq!(buf.len(), 0); + assert_eq!(buf.init_len(), 0); } #[test] diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs index 30812dabb4e..6adb734fb0a 100644 --- a/library/std/src/sys/unix/fd.rs +++ b/library/std/src/sys/unix/fd.rs @@ -4,7 +4,7 @@ mod tests; use crate::cmp; -use crate::io::{self, IoSlice, IoSliceMut, Read, ReadBuf}; +use crate::io::{self, BorrowCursor, IoSlice, IoSliceMut, Read}; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::sys::cvt; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -131,20 +131,19 @@ impl FileDesc { } } - pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + pub fn read_buf(&self, mut cursor: BorrowCursor<'_, '_>) -> io::Result<()> { let ret = cvt(unsafe { libc::read( self.as_raw_fd(), - buf.unfilled_mut().as_mut_ptr() as *mut libc::c_void, - cmp::min(buf.remaining(), READ_LIMIT), + cursor.as_mut().as_mut_ptr() as *mut libc::c_void, + cmp::min(cursor.capacity(), READ_LIMIT), ) })?; // Safety: `ret` bytes were written to the initialized portion of the buffer unsafe { - buf.assume_init(ret as usize); + cursor.advance(ret as usize); } - buf.add_filled(ret as usize); Ok(()) } diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index b5cc8038ca4..374f9f72d6d 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -2,7 +2,7 @@ use crate::os::unix::prelude::*; use crate::ffi::{CStr, CString, OsStr, OsString}; use crate::fmt; -use crate::io::{self, Error, IoSlice, IoSliceMut, ReadBuf, SeekFrom}; +use crate::io::{self, BorrowCursor, Error, IoSlice, IoSliceMut, SeekFrom}; use crate::mem; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd}; use crate::path::{Path, PathBuf}; @@ -1031,8 +1031,8 @@ impl File { self.0.read_at(buf, offset) } - pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - self.0.read_buf(buf) + pub fn read_buf(&self, cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + self.0.read_buf(cursor) } pub fn write(&self, buf: &[u8]) -> io::Result { -- cgit 1.4.1-3-g733a5 From b56cf67ce14580111ffb07a08a293e217566e116 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sun, 22 May 2022 20:57:58 -0500 Subject: Add some docs for BorrowBuf Signed-off-by: Nick Cameron --- library/std/src/io/readbuf.rs | 84 ++++++++++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 24 deletions(-) diff --git a/library/std/src/io/readbuf.rs b/library/std/src/io/readbuf.rs index 4578433b22a..8783763fd42 100644 --- a/library/std/src/io/readbuf.rs +++ b/library/std/src/io/readbuf.rs @@ -7,8 +7,7 @@ use crate::cmp; use crate::fmt::{self, Debug, Formatter}; use crate::mem::MaybeUninit; -// TODO docs -/// A wrapper around a byte buffer that is incrementally filled and initialized. +/// A borrowed byte buffer which is incrementally filled and initialized. /// /// This type is a sort of "double cursor". It tracks three regions in the buffer: a region at the beginning of the /// buffer that has been logically filled with data, a region that has been initialized at some point but not yet @@ -21,9 +20,20 @@ use crate::mem::MaybeUninit; /// [ filled | unfilled ] /// [ initialized | uninitialized ] /// ``` +/// +/// A `BorrowBuf` is created around some existing data (or capacity for data) via a unique reference +/// (`&mut`). The `BorrowBuf` can be configured (e.g., using `clear` or `set_init`), but otherwise +/// is read-only. To write into the buffer, use `unfilled` to create a `BorrowCursor`. The cursor +/// has write-only access to the unfilled portion of the buffer (you can think of it like a +/// write-only iterator). +/// +/// The lifetime `'a` is a bound on the lifetime of the underlying data. pub struct BorrowBuf<'a> { + /// The buffer's underlying data. buf: &'a mut [MaybeUninit], + /// The length of `self.buf` which is known to be filled. filled: usize, + /// The length of `self.buf` which is known to be initialized. initialized: usize, } @@ -37,7 +47,7 @@ impl Debug for BorrowBuf<'_> { } } -/// Creates a new `BorrowBuf` from a fully initialized slice. +/// Create a new `BorrowBuf` from a fully initialized slice. impl<'a> From<&'a mut [u8]> for BorrowBuf<'a> { #[inline] fn from(slice: &'a mut [u8]) -> BorrowBuf<'a> { @@ -52,7 +62,7 @@ impl<'a> From<&'a mut [u8]> for BorrowBuf<'a> { } } -/// Creates a new `BorrowBuf` from a fully uninitialized buffer. +/// Create a new `BorrowBuf` from an uninitialized buffer. /// /// Use `set_init` if part of the buffer is known to be already initialized. impl<'a> From<&'a mut [MaybeUninit]> for BorrowBuf<'a> { @@ -90,7 +100,7 @@ impl<'a> BorrowBuf<'a> { /// Returns a cursor over the unfilled part of the buffer. #[inline] - pub fn unfilled<'b>(&'b mut self) -> BorrowCursor<'a, 'b> { + pub fn unfilled<'this>(&'this mut self) -> BorrowCursor<'this, 'a> { BorrowCursor { start: self.filled, buf: self } } @@ -118,20 +128,36 @@ impl<'a> BorrowBuf<'a> { } } -/// A cursor view of a [`BorrowBuf`](BorrowBuf). +/// A writeable view of the unfilled portion of a [`BorrowBuf`](BorrowBuf). +/// +/// Provides access to the initialized and uninitialized parts of the underlying `BorrowBuf`. +/// Data can be written directly to the cursor by using [`append`](BorrowCursor::append) or +/// indirectly by getting a slice of part or all of the cursor and writing into the slice. In the +/// indirect case, the caller must call [`advance`](BorrowCursor::advance) after writing to inform +/// the cursor how many bytes have been written. /// -/// Provides mutable access to the unfilled portion (both initialised and uninitialised data) from -/// the buffer. +/// Once data is written to the cursor, it becomes part of the filled portion of the underlying +/// `BorrowBuf` and can no longer be accessed or re-written by the cursor. I.e., the cursor tracks +/// the unfilled part of the underlying `BorrowBuf`. +/// +/// The `'buf` lifetime is a bound on the lifetime of the underlying buffer. `'data` is a bound on +/// that buffer's underlying data. #[derive(Debug)] -pub struct BorrowCursor<'a, 'b> { - buf: &'b mut BorrowBuf<'a>, +pub struct BorrowCursor<'buf, 'data> { + /// The underlying buffer. + buf: &'buf mut BorrowBuf<'data>, + /// The length of the filled portion of the underlying buffer at the time of the cursor's + /// creation. start: usize, } -impl<'a, 'b> BorrowCursor<'a, 'b> { +impl<'buf, 'data> BorrowCursor<'buf, 'data> { /// Clone this cursor. + /// + /// Since a cursor maintains unique access to its underlying buffer, the cloned cursor is not + /// accessible while the clone is alive. #[inline] - pub fn clone<'c>(&'c mut self) -> BorrowCursor<'a, 'c> { + pub fn clone<'this>(&'this mut self) -> BorrowCursor<'this, 'data> { BorrowCursor { buf: self.buf, start: self.start } } @@ -141,14 +167,16 @@ impl<'a, 'b> BorrowCursor<'a, 'b> { self.buf.capacity() - self.buf.filled } - /// Returns the number of bytes written to this cursor. - // TODO check for reuse uses + /// Returns the number of bytes written to this cursor since it was created from a `BorrowBuf`. + /// + /// Note that if this cursor is a clone of another, then the count returned is the count written + /// via either cursor, not the count since the cursor was cloned. #[inline] pub fn written(&self) -> usize { self.buf.filled - self.start } - /// Returns a shared reference to the initialized portion of the buffer. + /// Returns a shared reference to the initialized portion of the cursor. #[inline] pub fn init_ref(&self) -> &[u8] { //SAFETY: We only slice the initialized part of the buffer, which is always valid @@ -157,7 +185,7 @@ impl<'a, 'b> BorrowCursor<'a, 'b> { } } - /// Returns a mutable reference to the initialized portion of the buffer. + /// Returns a mutable reference to the initialized portion of the cursor. #[inline] pub fn init_mut(&mut self) -> &mut [u8] { //SAFETY: We only slice the initialized part of the buffer, which is always valid @@ -168,7 +196,7 @@ impl<'a, 'b> BorrowCursor<'a, 'b> { } } - /// Returns a mutable reference to the uninitialized part of the buffer. + /// Returns a mutable reference to the uninitialized part of the cursor. /// /// It is safe to uninitialize any of these bytes. #[inline] @@ -176,17 +204,25 @@ impl<'a, 'b> BorrowCursor<'a, 'b> { &mut self.buf.buf[self.buf.initialized..] } - /// A view of the cursor as a mutable slice of `MaybeUninit`. + /// Returns a mutable reference to the whole cursor. + /// + /// # Safety + /// + /// The caller must not uninitialize any bytes in the initialized portion of the cursor. #[inline] pub unsafe fn as_mut(&mut self) -> &mut [MaybeUninit] { &mut self.buf.buf[self.buf.filled..] } - /// Increases the size of the filled region of the buffer. + /// Advance the cursor by asserting that `n` bytes have been filled. + /// + /// After advancing, the `n` bytes are no longer accessible via the cursor and can only be + /// accessed via the underlying buffer. I.e., the buffer's filled portion grows by `n` elements + /// and its unfilled portion (and the capacity of this cursor) shrinks by `n` elements. /// /// # Safety /// - /// The caller must ensure that the first `n` elements of the cursor have been properly + /// The caller must ensure that the first `n` bytes of the cursor have been properly /// initialised. #[inline] pub unsafe fn advance(&mut self, n: usize) -> &mut Self { @@ -195,7 +231,7 @@ impl<'a, 'b> BorrowCursor<'a, 'b> { self } - /// Initialised all bytes in the cursor. + /// Initializes all bytes in the cursor. #[inline] pub fn ensure_init(&mut self) -> &mut Self { for byte in self.uninit_mut() { @@ -208,8 +244,8 @@ impl<'a, 'b> BorrowCursor<'a, 'b> { /// Asserts that the first `n` unfilled bytes of the cursor are initialized. /// - /// `BorrowBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer - /// bytes than are already known to be initialized. + /// `BorrowBuf` assumes that bytes are never de-initialized, so this method does nothing when + /// called with fewer bytes than are already known to be initialized. /// /// # Safety /// @@ -220,7 +256,7 @@ impl<'a, 'b> BorrowCursor<'a, 'b> { self } - /// Appends data to the cursor, advancing the position within its buffer. + /// Appends data to the cursor, advancing position within its buffer. /// /// # Panics /// -- cgit 1.4.1-3-g733a5 From 012acdf8aeb86087ec34214a33f01e81c6a847b7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 5 Aug 2022 12:13:36 +0000 Subject: Update dependencies --- Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 352fd39a308..069f8cda1fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,9 +15,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704" +checksum = "c91f1f46651137be86f3a2b9a8359f9ab421d04d941c62b5982e1ca21113adf9" [[package]] name = "ar" @@ -232,9 +232,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b" [[package]] name = "libloading" @@ -290,9 +290,9 @@ checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" [[package]] name = "regalloc2" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ff2e57a7d050308b3fde0f707aa240b491b190e3855f212860f11bb3af4205" +checksum = "d43a209257d978ef079f3d446331d0f1794f5e0fc19b306a199983857833a779" dependencies = [ "fxhash", "log", -- cgit 1.4.1-3-g733a5 From 41d547892c03a34b32666f9c629147742fae579f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 5 Aug 2022 12:13:57 +0000 Subject: Re-introduce test.sh as convenience wrapper around ./y.rs test --- test.sh | 2 ++ 1 file changed, 2 insertions(+) create mode 100755 test.sh diff --git a/test.sh b/test.sh new file mode 100755 index 00000000000..3d929a1d50c --- /dev/null +++ b/test.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +exec ./y.rs test -- cgit 1.4.1-3-g733a5 From e7bc81cc772b37757077f6b0574eeb5382af3ac4 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 5 Aug 2022 12:57:19 +0000 Subject: Disable incr comp globally on CI --- build_system/build_backend.rs | 7 +++---- build_system/mod.rs | 7 +++++++ build_system/utils.rs | 5 +++++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/build_system/build_backend.rs b/build_system/build_backend.rs index 48faec8bc4b..cf04967222f 100644 --- a/build_system/build_backend.rs +++ b/build_system/build_backend.rs @@ -2,6 +2,8 @@ use std::env; use std::path::{Path, PathBuf}; use std::process::Command; +use super::utils::is_ci; + pub(crate) fn build_backend( channel: &str, host_triple: &str, @@ -14,12 +16,9 @@ pub(crate) fn build_backend( let mut rustflags = env::var("RUSTFLAGS").unwrap_or_default(); - if env::var("CI").as_ref().map(|val| &**val) == Ok("true") { + if is_ci() { // Deny warnings on CI rustflags += " -Dwarnings"; - - // Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway - cmd.env("CARGO_BUILD_INCREMENTAL", "false"); } if use_unstable_features { diff --git a/build_system/mod.rs b/build_system/mod.rs index 8c7d05993a5..88c4150dbba 100644 --- a/build_system/mod.rs +++ b/build_system/mod.rs @@ -2,6 +2,8 @@ use std::env; use std::path::PathBuf; use std::process; +use self::utils::is_ci; + mod build_backend; mod build_sysroot; mod config; @@ -48,6 +50,11 @@ pub fn main() { // The target dir is expected in the default location. Guard against the user changing it. env::set_var("CARGO_TARGET_DIR", "target"); + if is_ci() { + // Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway + env::set_var("CARGO_BUILD_INCREMENTAL", "false"); + } + let mut args = env::args().skip(1); let command = match args.next().as_deref() { Some("prepare") => { diff --git a/build_system/utils.rs b/build_system/utils.rs index 3282778e254..bdf8f8ecd99 100644 --- a/build_system/utils.rs +++ b/build_system/utils.rs @@ -1,3 +1,4 @@ +use std::env; use std::fs; use std::io::Write; use std::path::Path; @@ -55,3 +56,7 @@ pub(crate) fn copy_dir_recursively(from: &Path, to: &Path) { } } } + +pub(crate) fn is_ci() -> bool { + env::var("CI").as_ref().map(|val| &**val) == Ok("true") +} -- cgit 1.4.1-3-g733a5 From 3c97227a433c244f34fb8bb23afe41f259431d9b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 5 Aug 2022 13:17:13 +0000 Subject: Fix previous commit --- build_system/build_backend.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build_system/build_backend.rs b/build_system/build_backend.rs index cf04967222f..9e59b8199b4 100644 --- a/build_system/build_backend.rs +++ b/build_system/build_backend.rs @@ -19,6 +19,9 @@ pub(crate) fn build_backend( if is_ci() { // Deny warnings on CI rustflags += " -Dwarnings"; + + // Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway + cmd.env("CARGO_BUILD_INCREMENTAL", "false"); } if use_unstable_features { -- cgit 1.4.1-3-g733a5 From 1a2122fff015d1d7fb31fe3a55e49027d67d79af Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 7 Jun 2022 08:43:54 +0100 Subject: non-linux platforms Signed-off-by: Nick Cameron --- library/std/src/fs.rs | 6 +- library/std/src/io/buffered/bufreader.rs | 5 +- library/std/src/io/buffered/bufreader/buffer.rs | 12 ++- library/std/src/io/buffered/tests.rs | 12 +-- library/std/src/io/copy.rs | 8 +- library/std/src/io/cursor.rs | 4 +- library/std/src/io/impls.rs | 14 ++-- library/std/src/io/mod.rs | 21 +++-- library/std/src/io/readbuf.rs | 107 +++++++++++++----------- library/std/src/io/readbuf/tests.rs | 80 +++++++++++++++--- library/std/src/io/tests.rs | 6 +- library/std/src/io/util.rs | 6 +- library/std/src/io/util/tests.rs | 10 +-- library/std/src/sys/hermit/fs.rs | 6 +- library/std/src/sys/solid/fs.rs | 12 ++- library/std/src/sys/unix/fd.rs | 4 +- library/std/src/sys/unix/fs.rs | 4 +- library/std/src/sys/unsupported/fs.rs | 4 +- library/std/src/sys/wasi/fs.rs | 6 +- library/std/src/sys/windows/fs.rs | 6 +- library/std/src/sys/windows/handle.rs | 12 ++- 21 files changed, 205 insertions(+), 140 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index d41f32b5b3f..98aa40db321 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -13,7 +13,7 @@ mod tests; use crate::ffi::OsString; use crate::fmt; -use crate::io::{self, BorrowCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; use crate::path::{Path, PathBuf}; use crate::sys::fs as fs_imp; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; @@ -703,7 +703,7 @@ impl Read for File { self.inner.read_vectored(bufs) } - fn read_buf(&mut self, cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { self.inner.read_buf(cursor) } @@ -755,7 +755,7 @@ impl Read for &File { self.inner.read(buf) } - fn read_buf(&mut self, cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { self.inner.read_buf(cursor) } diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index 1f19ac11bf1..dced922ea57 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -2,8 +2,7 @@ mod buffer; use crate::fmt; use crate::io::{ - self, BorrowBuf, BorrowCursor, BufRead, IoSliceMut, Read, Seek, SeekFrom, SizeHint, - DEFAULT_BUF_SIZE, + self, BorrowedCursor, BufRead, IoSliceMut, Read, Seek, SeekFrom, SizeHint, DEFAULT_BUF_SIZE, }; use buffer::Buffer; @@ -267,7 +266,7 @@ impl Read for BufReader { Ok(nread) } - fn read_buf(&mut self, mut cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { // If we don't have any buffered data and we're doing a massive read // (larger than our internal buffer), bypass our internal buffer // entirely. diff --git a/library/std/src/io/buffered/bufreader/buffer.rs b/library/std/src/io/buffered/bufreader/buffer.rs index 8ae01f3b0ad..b122a6c0ccc 100644 --- a/library/std/src/io/buffered/bufreader/buffer.rs +++ b/library/std/src/io/buffered/bufreader/buffer.rs @@ -9,7 +9,7 @@ /// that user code which wants to do reads from a `BufReader` via `buffer` + `consume` can do so /// without encountering any runtime bounds checks. use crate::cmp; -use crate::io::{self, Read, ReadBuf}; +use crate::io::{self, BorrowedBuf, Read}; use crate::mem::MaybeUninit; pub struct Buffer { @@ -93,11 +93,15 @@ impl Buffer { if self.pos >= self.filled { debug_assert!(self.pos == self.filled); - let mut readbuf = ReadBuf::uninit(&mut self.buf); + let mut buf: BorrowedBuf<'_> = (&mut *self.buf).into(); + // SAFETY: `self.filled` bytes will always have been initialized. + unsafe { + buf.set_init(self.filled); + } - reader.read_buf(&mut readbuf)?; + reader.read_buf(buf.unfilled())?; - self.filled = readbuf.filled_len(); + self.filled = buf.len(); self.pos = 0; } Ok(self.buffer()) diff --git a/library/std/src/io/buffered/tests.rs b/library/std/src/io/buffered/tests.rs index c93b69bf1f7..bd6d95242ad 100644 --- a/library/std/src/io/buffered/tests.rs +++ b/library/std/src/io/buffered/tests.rs @@ -1,5 +1,7 @@ use crate::io::prelude::*; -use crate::io::{self, BorrowBuf, BufReader, BufWriter, ErrorKind, IoSlice, LineWriter, SeekFrom}; +use crate::io::{ + self, BorrowedBuf, BufReader, BufWriter, ErrorKind, IoSlice, LineWriter, SeekFrom, +}; use crate::mem::MaybeUninit; use crate::panic; use crate::sync::atomic::{AtomicUsize, Ordering}; @@ -62,7 +64,7 @@ fn test_buffered_reader_read_buf() { let mut reader = BufReader::with_capacity(2, inner); let buf: &mut [_] = &mut [MaybeUninit::uninit(); 3]; - let mut buf: BorrowBuf<'_> = buf.into(); + let mut buf: BorrowedBuf<'_> = buf.into(); reader.read_buf(buf.unfilled()).unwrap(); @@ -70,7 +72,7 @@ fn test_buffered_reader_read_buf() { assert_eq!(reader.buffer(), []); let buf: &mut [_] = &mut [MaybeUninit::uninit(); 2]; - let mut buf: BorrowBuf<'_> = buf.into(); + let mut buf: BorrowedBuf<'_> = buf.into(); reader.read_buf(buf.unfilled()).unwrap(); @@ -78,7 +80,7 @@ fn test_buffered_reader_read_buf() { assert_eq!(reader.buffer(), []); let buf: &mut [_] = &mut [MaybeUninit::uninit(); 1]; - let mut buf: BorrowBuf<'_> = buf.into(); + let mut buf: BorrowedBuf<'_> = buf.into(); reader.read_buf(buf.unfilled()).unwrap(); @@ -86,7 +88,7 @@ fn test_buffered_reader_read_buf() { assert_eq!(reader.buffer(), [3]); let buf: &mut [_] = &mut [MaybeUninit::uninit(); 3]; - let mut buf: BorrowBuf<'_> = buf.into(); + let mut buf: BorrowedBuf<'_> = buf.into(); reader.read_buf(buf.unfilled()).unwrap(); diff --git a/library/std/src/io/copy.rs b/library/std/src/io/copy.rs index 193bcd47467..1efd98b92aa 100644 --- a/library/std/src/io/copy.rs +++ b/library/std/src/io/copy.rs @@ -1,4 +1,4 @@ -use super::{BorrowBuf, BufWriter, ErrorKind, Read, Result, Write, DEFAULT_BUF_SIZE}; +use super::{BorrowedBuf, BufWriter, ErrorKind, Read, Result, Write, DEFAULT_BUF_SIZE}; use crate::mem::MaybeUninit; /// Copies the entire contents of a reader into a writer. @@ -97,7 +97,7 @@ impl BufferedCopySpec for BufWriter { loop { let buf = writer.buffer_mut(); - let mut read_buf: BorrowBuf<'_> = buf.spare_capacity_mut().into(); + let mut read_buf: BorrowedBuf<'_> = buf.spare_capacity_mut().into(); unsafe { // SAFETY: init is either 0 or the init_len from the previous iteration. @@ -117,7 +117,7 @@ impl BufferedCopySpec for BufWriter { init = read_buf.init_len() - bytes_read; len += bytes_read as u64; - // SAFETY: BorrowBuf guarantees all of its filled bytes are init + // SAFETY: BorrowedBuf guarantees all of its filled bytes are init unsafe { buf.set_len(buf.len() + bytes_read) }; // Read again if the buffer still has enough capacity, as BufWriter itself would do @@ -139,7 +139,7 @@ fn stack_buffer_copy( writer: &mut W, ) -> Result { let buf: &mut [_] = &mut [MaybeUninit::uninit(); DEFAULT_BUF_SIZE]; - let mut buf: BorrowBuf<'_> = buf.into(); + let mut buf: BorrowedBuf<'_> = buf.into(); let mut len = 0; diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index 460b1504ffb..e00577b5107 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -5,7 +5,7 @@ use crate::io::prelude::*; use crate::alloc::Allocator; use crate::cmp; -use crate::io::{self, BorrowCursor, ErrorKind, IoSlice, IoSliceMut, SeekFrom}; +use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut, SeekFrom}; /// A `Cursor` wraps an in-memory buffer and provides it with a /// [`Seek`] implementation. @@ -323,7 +323,7 @@ where Ok(n) } - fn read_buf(&mut self, mut cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { let prev_written = cursor.written(); Read::read_buf(&mut self.fill_buf()?, cursor.clone())?; diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index eee5ab6ec10..183c8c660b4 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -6,7 +6,7 @@ use crate::cmp; use crate::collections::VecDeque; use crate::fmt; use crate::io::{ - self, BorrowCursor, BufRead, ErrorKind, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write, + self, BorrowedCursor, BufRead, ErrorKind, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write, }; use crate::mem; @@ -21,7 +21,7 @@ impl Read for &mut R { } #[inline] - fn read_buf(&mut self, cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { (**self).read_buf(cursor) } @@ -125,7 +125,7 @@ impl Read for Box { } #[inline] - fn read_buf(&mut self, cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { (**self).read_buf(cursor) } @@ -249,7 +249,7 @@ impl Read for &[u8] { } #[inline] - fn read_buf(&mut self, mut cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { let amt = cmp::min(cursor.capacity(), self.len()); let (a, b) = self.split_at(amt); @@ -427,10 +427,10 @@ impl Read for VecDeque { } #[inline] - fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + fn read_buf(&mut self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { let (ref mut front, _) = self.as_slices(); - let n = cmp::min(buf.remaining(), front.len()); - Read::read_buf(front, buf)?; + let n = cmp::min(cursor.capacity(), front.len()); + Read::read_buf(front, cursor)?; self.drain(..n); Ok(()) } diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index b3218b2831d..02f82a7e995 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -278,7 +278,7 @@ pub use self::{ }; #[unstable(feature = "read_buf", issue = "78485")] -pub use self::readbuf::{BorrowBuf, BorrowCursor}; +pub use self::readbuf::{BorrowedBuf, BorrowedCursor}; pub(crate) use error::const_io_error; mod buffered; @@ -362,7 +362,7 @@ pub(crate) fn default_read_to_end(r: &mut R, buf: &mut Vec buf.reserve(32); // buf is full, need more space } - let mut read_buf: BorrowBuf<'_> = buf.spare_capacity_mut().into(); + let mut read_buf: BorrowedBuf<'_> = buf.spare_capacity_mut().into(); // SAFETY: These bytes were initialized but not filled in the previous loop unsafe { @@ -383,7 +383,7 @@ pub(crate) fn default_read_to_end(r: &mut R, buf: &mut Vec // store how much was initialized but not filled initialized = cursor.init_ref().len(); - // SAFETY: BorrowBuf's invariants mean this much memory is initialized. + // SAFETY: BorrowedBuf's invariants mean this much memory is initialized. unsafe { let new_len = read_buf.filled().len() + buf.len(); buf.set_len(new_len); @@ -462,7 +462,7 @@ pub(crate) fn default_read_exact(this: &mut R, mut buf: &mut [ } } -pub(crate) fn default_read_buf(read: F, mut cursor: BorrowCursor<'_, '_>) -> Result<()> +pub(crate) fn default_read_buf(read: F, mut cursor: BorrowedCursor<'_, '_>) -> Result<()> where F: FnOnce(&mut [u8]) -> Result, { @@ -805,24 +805,23 @@ pub trait Read { default_read_exact(self, buf) } - // TODO naming, if should the method be read_cursor? Or should we change the names of the data structures? /// Pull some bytes from this source into the specified buffer. /// - /// This is equivalent to the [`read`](Read::read) method, except that it is passed a [`BorrowCursor`] rather than `[u8]` to allow use + /// This is equivalent to the [`read`](Read::read) method, except that it is passed a [`BorrowedCursor`] rather than `[u8]` to allow use /// with uninitialized buffers. The new data will be appended to any existing contents of `buf`. /// /// The default implementation delegates to `read`. #[unstable(feature = "read_buf", issue = "78485")] - fn read_buf(&mut self, buf: BorrowCursor<'_, '_>) -> Result<()> { + fn read_buf(&mut self, buf: BorrowedCursor<'_, '_>) -> Result<()> { default_read_buf(|b| self.read(b), buf) } /// Read the exact number of bytes required to fill `cursor`. /// - /// This is equivalent to the [`read_exact`](Read::read_exact) method, except that it is passed a [`BorrowCursor`] rather than `[u8]` to + /// This is equivalent to the [`read_exact`](Read::read_exact) method, except that it is passed a [`BorrowedCursor`] rather than `[u8]` to /// allow use with uninitialized buffers. #[unstable(feature = "read_buf", issue = "78485")] - fn read_buf_exact(&mut self, mut cursor: BorrowCursor<'_, '_>) -> Result<()> { + fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_, '_>) -> Result<()> { while cursor.capacity() > 0 { let prev_written = cursor.written(); match self.read_buf(cursor.clone()) { @@ -2587,7 +2586,7 @@ impl Read for Take { Ok(n) } - fn read_buf(&mut self, mut buf: BorrowCursor<'_, '_>) -> Result<()> { + fn read_buf(&mut self, mut buf: BorrowedCursor<'_, '_>) -> Result<()> { // Don't call into inner reader at all at EOF because it may still block if self.limit == 0 { return Ok(()); @@ -2602,7 +2601,7 @@ impl Read for Take { // SAFETY: no uninit data is written to ibuf let ibuf = unsafe { &mut buf.as_mut()[..limit] }; - let mut sliced_buf: BorrowBuf<'_> = ibuf.into(); + let mut sliced_buf: BorrowedBuf<'_> = ibuf.into(); // SAFETY: extra_init bytes of ibuf are known to be initialized unsafe { diff --git a/library/std/src/io/readbuf.rs b/library/std/src/io/readbuf.rs index 8783763fd42..ae3fbcc6a2f 100644 --- a/library/std/src/io/readbuf.rs +++ b/library/std/src/io/readbuf.rs @@ -5,6 +5,7 @@ mod tests; use crate::cmp; use crate::fmt::{self, Debug, Formatter}; +use crate::io::{Result, Write}; use crate::mem::MaybeUninit; /// A borrowed byte buffer which is incrementally filled and initialized. @@ -21,58 +22,58 @@ use crate::mem::MaybeUninit; /// [ initialized | uninitialized ] /// ``` /// -/// A `BorrowBuf` is created around some existing data (or capacity for data) via a unique reference -/// (`&mut`). The `BorrowBuf` can be configured (e.g., using `clear` or `set_init`), but otherwise -/// is read-only. To write into the buffer, use `unfilled` to create a `BorrowCursor`. The cursor +/// A `BorrowedBuf` is created around some existing data (or capacity for data) via a unique reference +/// (`&mut`). The `BorrowedBuf` can be configured (e.g., using `clear` or `set_init`), but otherwise +/// is read-only. To write into the buffer, use `unfilled` to create a `BorrowedCursor`. The cursor /// has write-only access to the unfilled portion of the buffer (you can think of it like a /// write-only iterator). /// -/// The lifetime `'a` is a bound on the lifetime of the underlying data. -pub struct BorrowBuf<'a> { +/// The lifetime `'data` is a bound on the lifetime of the underlying data. +pub struct BorrowedBuf<'data> { /// The buffer's underlying data. - buf: &'a mut [MaybeUninit], + buf: &'data mut [MaybeUninit], /// The length of `self.buf` which is known to be filled. filled: usize, /// The length of `self.buf` which is known to be initialized. - initialized: usize, + init: usize, } -impl Debug for BorrowBuf<'_> { +impl Debug for BorrowedBuf<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.debug_struct("ReadBuf") - .field("init", &self.initialized) + f.debug_struct("BorrowedBuf") + .field("init", &self.init) .field("filled", &self.filled) .field("capacity", &self.capacity()) .finish() } } -/// Create a new `BorrowBuf` from a fully initialized slice. -impl<'a> From<&'a mut [u8]> for BorrowBuf<'a> { +/// Create a new `BorrowedBuf` from a fully initialized slice. +impl<'data> From<&'data mut [u8]> for BorrowedBuf<'data> { #[inline] - fn from(slice: &'a mut [u8]) -> BorrowBuf<'a> { + fn from(slice: &'data mut [u8]) -> BorrowedBuf<'data> { let len = slice.len(); - BorrowBuf { - //SAFETY: initialized data never becoming uninitialized is an invariant of BorrowBuf + BorrowedBuf { + //SAFETY: initialized data never becoming uninitialized is an invariant of BorrowedBuf buf: unsafe { (slice as *mut [u8]).as_uninit_slice_mut().unwrap() }, filled: 0, - initialized: len, + init: len, } } } -/// Create a new `BorrowBuf` from an uninitialized buffer. +/// Create a new `BorrowedBuf` from an uninitialized buffer. /// /// Use `set_init` if part of the buffer is known to be already initialized. -impl<'a> From<&'a mut [MaybeUninit]> for BorrowBuf<'a> { +impl<'data> From<&'data mut [MaybeUninit]> for BorrowedBuf<'data> { #[inline] - fn from(buf: &'a mut [MaybeUninit]) -> BorrowBuf<'a> { - BorrowBuf { buf, filled: 0, initialized: 0 } + fn from(buf: &'data mut [MaybeUninit]) -> BorrowedBuf<'data> { + BorrowedBuf { buf, filled: 0, init: 0 } } } -impl<'a> BorrowBuf<'a> { +impl<'data> BorrowedBuf<'data> { /// Returns the total capacity of the buffer. #[inline] pub fn capacity(&self) -> usize { @@ -88,7 +89,7 @@ impl<'a> BorrowBuf<'a> { /// Returns the length of the initialized part of the buffer. #[inline] pub fn init_len(&self) -> usize { - self.initialized + self.init } /// Returns a shared reference to the filled portion of the buffer. @@ -100,8 +101,8 @@ impl<'a> BorrowBuf<'a> { /// Returns a cursor over the unfilled part of the buffer. #[inline] - pub fn unfilled<'this>(&'this mut self) -> BorrowCursor<'this, 'a> { - BorrowCursor { start: self.filled, buf: self } + pub fn unfilled<'this>(&'this mut self) -> BorrowedCursor<'this, 'data> { + BorrowedCursor { start: self.filled, buf: self } } /// Clears the buffer, resetting the filled region to empty. @@ -115,7 +116,7 @@ impl<'a> BorrowBuf<'a> { /// Asserts that the first `n` bytes of the buffer are initialized. /// - /// `BorrowBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer + /// `BorrowedBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer /// bytes than are already known to be initialized. /// /// # Safety @@ -123,42 +124,42 @@ impl<'a> BorrowBuf<'a> { /// The caller must ensure that the first `n` unfilled bytes of the buffer have already been initialized. #[inline] pub unsafe fn set_init(&mut self, n: usize) -> &mut Self { - self.initialized = cmp::max(self.initialized, n); + self.init = cmp::max(self.init, n); self } } -/// A writeable view of the unfilled portion of a [`BorrowBuf`](BorrowBuf). +/// A writeable view of the unfilled portion of a [`BorrowedBuf`](BorrowedBuf). /// -/// Provides access to the initialized and uninitialized parts of the underlying `BorrowBuf`. -/// Data can be written directly to the cursor by using [`append`](BorrowCursor::append) or +/// Provides access to the initialized and uninitialized parts of the underlying `BorrowedBuf`. +/// Data can be written directly to the cursor by using [`append`](BorrowedCursor::append) or /// indirectly by getting a slice of part or all of the cursor and writing into the slice. In the -/// indirect case, the caller must call [`advance`](BorrowCursor::advance) after writing to inform +/// indirect case, the caller must call [`advance`](BorrowedCursor::advance) after writing to inform /// the cursor how many bytes have been written. /// /// Once data is written to the cursor, it becomes part of the filled portion of the underlying -/// `BorrowBuf` and can no longer be accessed or re-written by the cursor. I.e., the cursor tracks -/// the unfilled part of the underlying `BorrowBuf`. +/// `BorrowedBuf` and can no longer be accessed or re-written by the cursor. I.e., the cursor tracks +/// the unfilled part of the underlying `BorrowedBuf`. /// /// The `'buf` lifetime is a bound on the lifetime of the underlying buffer. `'data` is a bound on /// that buffer's underlying data. #[derive(Debug)] -pub struct BorrowCursor<'buf, 'data> { +pub struct BorrowedCursor<'buf, 'data> { /// The underlying buffer. - buf: &'buf mut BorrowBuf<'data>, + buf: &'buf mut BorrowedBuf<'data>, /// The length of the filled portion of the underlying buffer at the time of the cursor's /// creation. start: usize, } -impl<'buf, 'data> BorrowCursor<'buf, 'data> { +impl<'buf, 'data> BorrowedCursor<'buf, 'data> { /// Clone this cursor. /// /// Since a cursor maintains unique access to its underlying buffer, the cloned cursor is not /// accessible while the clone is alive. #[inline] - pub fn clone<'this>(&'this mut self) -> BorrowCursor<'this, 'data> { - BorrowCursor { buf: self.buf, start: self.start } + pub fn clone<'this>(&'this mut self) -> BorrowedCursor<'this, 'data> { + BorrowedCursor { buf: self.buf, start: self.start } } /// Returns the available space in the cursor. @@ -167,7 +168,7 @@ impl<'buf, 'data> BorrowCursor<'buf, 'data> { self.buf.capacity() - self.buf.filled } - /// Returns the number of bytes written to this cursor since it was created from a `BorrowBuf`. + /// Returns the number of bytes written to this cursor since it was created from a `BorrowedBuf`. /// /// Note that if this cursor is a clone of another, then the count returned is the count written /// via either cursor, not the count since the cursor was cloned. @@ -180,9 +181,7 @@ impl<'buf, 'data> BorrowCursor<'buf, 'data> { #[inline] pub fn init_ref(&self) -> &[u8] { //SAFETY: We only slice the initialized part of the buffer, which is always valid - unsafe { - MaybeUninit::slice_assume_init_ref(&self.buf.buf[self.buf.filled..self.buf.initialized]) - } + unsafe { MaybeUninit::slice_assume_init_ref(&self.buf.buf[self.buf.filled..self.buf.init]) } } /// Returns a mutable reference to the initialized portion of the cursor. @@ -190,9 +189,7 @@ impl<'buf, 'data> BorrowCursor<'buf, 'data> { pub fn init_mut(&mut self) -> &mut [u8] { //SAFETY: We only slice the initialized part of the buffer, which is always valid unsafe { - MaybeUninit::slice_assume_init_mut( - &mut self.buf.buf[self.buf.filled..self.buf.initialized], - ) + MaybeUninit::slice_assume_init_mut(&mut self.buf.buf[self.buf.filled..self.buf.init]) } } @@ -201,7 +198,7 @@ impl<'buf, 'data> BorrowCursor<'buf, 'data> { /// It is safe to uninitialize any of these bytes. #[inline] pub fn uninit_mut(&mut self) -> &mut [MaybeUninit] { - &mut self.buf.buf[self.buf.initialized..] + &mut self.buf.buf[self.buf.init..] } /// Returns a mutable reference to the whole cursor. @@ -227,7 +224,7 @@ impl<'buf, 'data> BorrowCursor<'buf, 'data> { #[inline] pub unsafe fn advance(&mut self, n: usize) -> &mut Self { self.buf.filled += n; - self.buf.initialized = cmp::max(self.buf.initialized, self.buf.filled); + self.buf.init = cmp::max(self.buf.init, self.buf.filled); self } @@ -237,14 +234,14 @@ impl<'buf, 'data> BorrowCursor<'buf, 'data> { for byte in self.uninit_mut() { byte.write(0); } - self.buf.initialized = self.buf.capacity(); + self.buf.init = self.buf.capacity(); self } /// Asserts that the first `n` unfilled bytes of the cursor are initialized. /// - /// `BorrowBuf` assumes that bytes are never de-initialized, so this method does nothing when + /// `BorrowedBuf` assumes that bytes are never de-initialized, so this method does nothing when /// called with fewer bytes than are already known to be initialized. /// /// # Safety @@ -252,7 +249,7 @@ impl<'buf, 'data> BorrowCursor<'buf, 'data> { /// The caller must ensure that the first `n` bytes of the buffer have already been initialized. #[inline] pub unsafe fn set_init(&mut self, n: usize) -> &mut Self { - self.buf.initialized = cmp::max(self.buf.initialized, self.buf.filled + n); + self.buf.init = cmp::max(self.buf.init, self.buf.filled + n); self } @@ -272,9 +269,19 @@ impl<'buf, 'data> BorrowCursor<'buf, 'data> { // SAFETY: We just added the entire contents of buf to the filled section. unsafe { - self.set_init(buf.len()); } self.buf.filled += buf.len(); } } + +impl<'buf, 'data> Write for BorrowedCursor<'buf, 'data> { + fn write(&mut self, buf: &[u8]) -> Result { + self.append(buf); + Ok(buf.len()) + } + + fn flush(&mut self) -> Result<()> { + Ok(()) + } +} diff --git a/library/std/src/io/readbuf/tests.rs b/library/std/src/io/readbuf/tests.rs index 584e5de982e..8037a957908 100644 --- a/library/std/src/io/readbuf/tests.rs +++ b/library/std/src/io/readbuf/tests.rs @@ -1,11 +1,11 @@ -use super::BorrowBuf; +use super::BorrowedBuf; use crate::mem::MaybeUninit; -/// Test that BorrowBuf has the correct numbers when created with new +/// Test that BorrowedBuf has the correct numbers when created with new #[test] fn new() { let buf: &mut [_] = &mut [0; 16]; - let mut rbuf: BorrowBuf<'_> = buf.into(); + let mut rbuf: BorrowedBuf<'_> = buf.into(); assert_eq!(rbuf.filled().len(), 0); assert_eq!(rbuf.init_len(), 16); @@ -13,11 +13,11 @@ fn new() { assert_eq!(rbuf.unfilled().capacity(), 16); } -/// Test that BorrowBuf has the correct numbers when created with uninit +/// Test that BorrowedBuf has the correct numbers when created with uninit #[test] fn uninit() { let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16]; - let mut rbuf: BorrowBuf<'_> = buf.into(); + let mut rbuf: BorrowedBuf<'_> = buf.into(); assert_eq!(rbuf.filled().len(), 0); assert_eq!(rbuf.init_len(), 0); @@ -28,7 +28,7 @@ fn uninit() { #[test] fn initialize_unfilled() { let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16]; - let mut rbuf: BorrowBuf<'_> = buf.into(); + let mut rbuf: BorrowedBuf<'_> = buf.into(); rbuf.unfilled().ensure_init(); @@ -36,9 +36,9 @@ fn initialize_unfilled() { } #[test] -fn add_filled() { +fn addvance_filled() { let buf: &mut [_] = &mut [0; 16]; - let mut rbuf: BorrowBuf<'_> = buf.into(); + let mut rbuf: BorrowedBuf<'_> = buf.into(); unsafe { rbuf.unfilled().advance(1); @@ -51,7 +51,7 @@ fn add_filled() { #[test] fn clear() { let buf: &mut [_] = &mut [255; 16]; - let mut rbuf: BorrowBuf<'_> = buf.into(); + let mut rbuf: BorrowedBuf<'_> = buf.into(); unsafe { rbuf.unfilled().advance(16); @@ -71,7 +71,7 @@ fn clear() { #[test] fn set_init() { let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16]; - let mut rbuf: BorrowBuf<'_> = buf.into(); + let mut rbuf: BorrowedBuf<'_> = buf.into(); unsafe { rbuf.set_init(8); @@ -99,7 +99,7 @@ fn set_init() { #[test] fn append() { let buf: &mut [_] = &mut [MaybeUninit::new(255); 16]; - let mut rbuf: BorrowBuf<'_> = buf.into(); + let mut rbuf: BorrowedBuf<'_> = buf.into(); rbuf.unfilled().append(&[0; 8]); @@ -115,3 +115,61 @@ fn append() { assert_eq!(rbuf.filled().len(), 16); assert_eq!(rbuf.filled(), [1; 16]); } + +#[test] +fn clone_written() { + let buf: &mut [_] = &mut [MaybeUninit::new(0); 32]; + let mut buf: BorrowedBuf<'_> = buf.into(); + + let mut cursor = buf.unfilled(); + cursor.append(&[1; 16]); + + let mut cursor2 = cursor.clone(); + cursor2.append(&[2; 16]); + + assert_eq!(cursor2.written(), 32); + assert_eq!(cursor.written(), 32); + + assert_eq!(buf.unfilled().written(), 0); + assert_eq!(buf.init_len(), 32); + assert_eq!(buf.filled().len(), 32); + let filled = buf.filled(); + assert_eq!(&filled[..16], [1; 16]); + assert_eq!(&filled[16..], [2; 16]); +} + +#[test] +fn cursor_set_init() { + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16]; + let mut rbuf: BorrowedBuf<'_> = buf.into(); + + unsafe { + rbuf.unfilled().set_init(8); + } + + assert_eq!(rbuf.init_len(), 8); + assert_eq!(rbuf.unfilled().init_ref().len(), 8); + assert_eq!(rbuf.unfilled().init_mut().len(), 8); + assert_eq!(rbuf.unfilled().uninit_mut().len(), 8); + assert_eq!(unsafe { rbuf.unfilled().as_mut() }.len(), 16); + + unsafe { + rbuf.unfilled().advance(4); + } + + unsafe { + rbuf.unfilled().set_init(2); + } + + assert_eq!(rbuf.init_len(), 8); + + unsafe { + rbuf.unfilled().set_init(8); + } + + assert_eq!(rbuf.init_len(), 12); + assert_eq!(rbuf.unfilled().init_ref().len(), 8); + assert_eq!(rbuf.unfilled().init_mut().len(), 8); + assert_eq!(rbuf.unfilled().uninit_mut().len(), 4); + assert_eq!(unsafe { rbuf.unfilled().as_mut() }.len(), 12); +} diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index a1322a18565..c5c476ec3bf 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -1,4 +1,4 @@ -use super::{repeat, BorrowBuf, Cursor, SeekFrom}; +use super::{repeat, BorrowedBuf, Cursor, SeekFrom}; use crate::cmp::{self, min}; use crate::io::{self, IoSlice, IoSliceMut}; use crate::io::{BufRead, BufReader, Read, Seek, Write}; @@ -160,7 +160,7 @@ fn read_exact_slice() { #[test] fn read_buf_exact() { let buf: &mut [_] = &mut [0; 4]; - let mut buf: BorrowBuf<'_> = buf.into(); + let mut buf: BorrowedBuf<'_> = buf.into(); let mut c = Cursor::new(&b""[..]); assert_eq!(c.read_buf_exact(buf.unfilled()).unwrap_err().kind(), io::ErrorKind::UnexpectedEof); @@ -616,7 +616,7 @@ fn bench_take_read_buf(b: &mut test::Bencher) { b.iter(|| { let buf: &mut [_] = &mut [MaybeUninit::uninit(); 64]; - let mut buf: BorrowBuf<'_> = buf.into(); + let mut buf: BorrowedBuf<'_> = buf.into(); [255; 128].take(64).read_buf(buf.unfilled()).unwrap(); }); diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index 5149926fd51..7475d71119a 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -5,7 +5,7 @@ mod tests; use crate::fmt; use crate::io::{ - self, BorrowCursor, BufRead, IoSlice, IoSliceMut, Read, Seek, SeekFrom, SizeHint, Write, + self, BorrowedCursor, BufRead, IoSlice, IoSliceMut, Read, Seek, SeekFrom, SizeHint, Write, }; /// A reader which is always at EOF. @@ -47,7 +47,7 @@ impl Read for Empty { } #[inline] - fn read_buf(&mut self, _cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, _cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { Ok(()) } } @@ -130,7 +130,7 @@ impl Read for Repeat { Ok(buf.len()) } - fn read_buf(&mut self, mut buf: BorrowCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, mut buf: BorrowedCursor<'_, '_>) -> io::Result<()> { // SAFETY: No uninit bytes are being written for slot in unsafe { buf.as_mut() } { slot.write(self.byte); diff --git a/library/std/src/io/util/tests.rs b/library/std/src/io/util/tests.rs index 025173c3f44..ce5e2c9da1d 100644 --- a/library/std/src/io/util/tests.rs +++ b/library/std/src/io/util/tests.rs @@ -1,7 +1,7 @@ use crate::cmp::{max, min}; use crate::io::prelude::*; use crate::io::{ - copy, empty, repeat, sink, BorrowBuf, BufWriter, Empty, Repeat, Result, SeekFrom, Sink, + copy, empty, repeat, sink, BorrowedBuf, BufWriter, Empty, Repeat, Result, SeekFrom, Sink, DEFAULT_BUF_SIZE, }; @@ -80,25 +80,25 @@ fn empty_reads() { assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0); let buf: &mut [MaybeUninit<_>] = &mut []; - let mut buf: BorrowBuf<'_> = buf.into(); + let mut buf: BorrowedBuf<'_> = buf.into(); e.read_buf(buf.unfilled()).unwrap(); assert_eq!(buf.len(), 0); assert_eq!(buf.init_len(), 0); let buf: &mut [_] = &mut [MaybeUninit::uninit()]; - let mut buf: BorrowBuf<'_> = buf.into(); + let mut buf: BorrowedBuf<'_> = buf.into(); e.read_buf(buf.unfilled()).unwrap(); assert_eq!(buf.len(), 0); assert_eq!(buf.init_len(), 0); let buf: &mut [_] = &mut [MaybeUninit::uninit(); 1024]; - let mut buf: BorrowBuf<'_> = buf.into(); + let mut buf: BorrowedBuf<'_> = buf.into(); e.read_buf(buf.unfilled()).unwrap(); assert_eq!(buf.len(), 0); assert_eq!(buf.init_len(), 0); let buf: &mut [_] = &mut [MaybeUninit::uninit(); 1024]; - let mut buf: BorrowBuf<'_> = buf.into(); + let mut buf: BorrowedBuf<'_> = buf.into(); e.by_ref().read_buf(buf.unfilled()).unwrap(); assert_eq!(buf.len(), 0); assert_eq!(buf.init_len(), 0); diff --git a/library/std/src/sys/hermit/fs.rs b/library/std/src/sys/hermit/fs.rs index fa9a7fb19e4..51321c51972 100644 --- a/library/std/src/sys/hermit/fs.rs +++ b/library/std/src/sys/hermit/fs.rs @@ -2,7 +2,7 @@ use crate::ffi::{CStr, CString, OsString}; use crate::fmt; use crate::hash::{Hash, Hasher}; use crate::io::{self, Error, ErrorKind}; -use crate::io::{IoSlice, IoSliceMut, ReadBuf, SeekFrom}; +use crate::io::{BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; use crate::os::unix::ffi::OsStrExt; use crate::path::{Path, PathBuf}; use crate::sys::cvt; @@ -312,8 +312,8 @@ impl File { false } - pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - crate::io::default_read_buf(|buf| self.read(buf), buf) + pub fn read_buf(&self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + crate::io::default_read_buf(|buf| self.read(buf), cursor) } pub fn write(&self, buf: &[u8]) -> io::Result { diff --git a/library/std/src/sys/solid/fs.rs b/library/std/src/sys/solid/fs.rs index a2cbee4dcf0..0848d3d8f10 100644 --- a/library/std/src/sys/solid/fs.rs +++ b/library/std/src/sys/solid/fs.rs @@ -2,7 +2,7 @@ use super::{abi, error}; use crate::{ ffi::{CStr, CString, OsStr, OsString}, fmt, - io::{self, IoSlice, IoSliceMut, ReadBuf, SeekFrom}, + io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}, mem::MaybeUninit, os::raw::{c_int, c_short}, os::solid::ffi::OsStrExt, @@ -358,13 +358,13 @@ impl File { } } - pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + pub fn read_buf(&self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { unsafe { - let len = buf.remaining(); + let len = cursor.capacity(); let mut out_num_bytes = MaybeUninit::uninit(); error::SolidError::err_if_negative(abi::SOLID_FS_Read( self.fd.raw(), - buf.unfilled_mut().as_mut_ptr() as *mut u8, + cursor.as_mut().as_mut_ptr() as *mut u8, len, out_num_bytes.as_mut_ptr(), )) @@ -376,9 +376,7 @@ impl File { // Safety: `num_bytes_read` bytes were written to the unfilled // portion of the buffer - buf.assume_init(num_bytes_read); - - buf.add_filled(num_bytes_read); + cursor.advance(num_bytes_read); Ok(()) } diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs index 6adb734fb0a..76a269bb9b5 100644 --- a/library/std/src/sys/unix/fd.rs +++ b/library/std/src/sys/unix/fd.rs @@ -4,7 +4,7 @@ mod tests; use crate::cmp; -use crate::io::{self, BorrowCursor, IoSlice, IoSliceMut, Read}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read}; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::sys::cvt; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -131,7 +131,7 @@ impl FileDesc { } } - pub fn read_buf(&self, mut cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + pub fn read_buf(&self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { let ret = cvt(unsafe { libc::read( self.as_raw_fd(), diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 374f9f72d6d..50561345442 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -2,7 +2,7 @@ use crate::os::unix::prelude::*; use crate::ffi::{CStr, CString, OsStr, OsString}; use crate::fmt; -use crate::io::{self, BorrowCursor, Error, IoSlice, IoSliceMut, SeekFrom}; +use crate::io::{self, BorrowedCursor, Error, IoSlice, IoSliceMut, SeekFrom}; use crate::mem; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd}; use crate::path::{Path, PathBuf}; @@ -1031,7 +1031,7 @@ impl File { self.0.read_at(buf, offset) } - pub fn read_buf(&self, cursor: BorrowCursor<'_, '_>) -> io::Result<()> { + pub fn read_buf(&self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { self.0.read_buf(cursor) } diff --git a/library/std/src/sys/unsupported/fs.rs b/library/std/src/sys/unsupported/fs.rs index 0e1a6257ed7..41e39ce27ce 100644 --- a/library/std/src/sys/unsupported/fs.rs +++ b/library/std/src/sys/unsupported/fs.rs @@ -1,7 +1,7 @@ use crate::ffi::OsString; use crate::fmt; use crate::hash::{Hash, Hasher}; -use crate::io::{self, IoSlice, IoSliceMut, ReadBuf, SeekFrom}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; use crate::path::{Path, PathBuf}; use crate::sys::time::SystemTime; use crate::sys::unsupported; @@ -214,7 +214,7 @@ impl File { self.0 } - pub fn read_buf(&self, _buf: &mut ReadBuf<'_>) -> io::Result<()> { + pub fn read_buf(&self, _cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { self.0 } diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index 6614ae397b5..b5b5eab1a24 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -3,7 +3,7 @@ use super::fd::WasiFd; use crate::ffi::{CStr, CString, OsStr, OsString}; use crate::fmt; -use crate::io::{self, IoSlice, IoSliceMut, ReadBuf, SeekFrom}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; use crate::iter; use crate::mem::{self, ManuallyDrop}; use crate::os::raw::c_int; @@ -439,8 +439,8 @@ impl File { true } - pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - crate::io::default_read_buf(|buf| self.read(buf), buf) + pub fn read_buf(&self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + crate::io::default_read_buf(|buf| self.read(buf), cursor) } pub fn write(&self, buf: &[u8]) -> io::Result { diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index aed082b3e0a..bfc2477dff4 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -2,7 +2,7 @@ use crate::os::windows::prelude::*; use crate::ffi::OsString; use crate::fmt; -use crate::io::{self, Error, IoSlice, IoSliceMut, ReadBuf, SeekFrom}; +use crate::io::{self, BorrowedCursor, Error, IoSlice, IoSliceMut, SeekFrom}; use crate::mem; use crate::os::windows::io::{AsHandle, BorrowedHandle}; use crate::path::{Path, PathBuf}; @@ -415,8 +415,8 @@ impl File { self.handle.read_at(buf, offset) } - pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - self.handle.read_buf(buf) + pub fn read_buf(&self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + self.handle.read_buf(cursor) } pub fn write(&self, buf: &[u8]) -> io::Result { diff --git a/library/std/src/sys/windows/handle.rs b/library/std/src/sys/windows/handle.rs index e24b09cc96e..0ea6876af5b 100644 --- a/library/std/src/sys/windows/handle.rs +++ b/library/std/src/sys/windows/handle.rs @@ -4,7 +4,7 @@ mod tests; use crate::cmp; -use crate::io::{self, ErrorKind, IoSlice, IoSliceMut, Read, ReadBuf}; +use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut, Read}; use crate::mem; use crate::os::windows::io::{ AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, RawHandle, @@ -112,18 +112,16 @@ impl Handle { } } - pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { - let res = unsafe { - self.synchronous_read(buf.unfilled_mut().as_mut_ptr(), buf.remaining(), None) - }; + pub fn read_buf(&self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + let res = + unsafe { self.synchronous_read(cursor.as_mut().as_mut_ptr(), cursor.capacity(), None) }; match res { Ok(read) => { // Safety: `read` bytes were written to the initialized portion of the buffer unsafe { - buf.assume_init(read as usize); + cursor.advance(read as usize); } - buf.add_filled(read as usize); Ok(()) } -- cgit 1.4.1-3-g733a5 From 3bd9821342d57081aea18cbb53271a20769eaf03 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 6 Aug 2022 13:34:55 +0100 Subject: Initial ABI Checker support --- .gitignore | 1 + build_system/abi_checker.rs | 67 +++++++++++++++++++++++++++++++++++++++++++++ build_system/mod.rs | 16 +++++++++++ build_system/prepare.rs | 7 +++++ 4 files changed, 91 insertions(+) create mode 100644 build_system/abi_checker.rs diff --git a/.gitignore b/.gitignore index 38dd5b26063..6fd3e4443de 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ perf.data.old /regex /simple-raytracer /portable-simd +/abi-checker diff --git a/build_system/abi_checker.rs b/build_system/abi_checker.rs new file mode 100644 index 00000000000..1aff4acc21b --- /dev/null +++ b/build_system/abi_checker.rs @@ -0,0 +1,67 @@ +use super::build_sysroot; +use super::utils::spawn_and_wait_with_input; +use build_system::SysrootKind; +use std::env; +use std::path::Path; +use std::process::Command; + +pub(crate) fn run( + channel: &str, + sysroot_kind: SysrootKind, + target_dir: &Path, + cg_clif_build_dir: &Path, + host_triple: &str, + target_triple: &str, +) { + assert_eq!( + host_triple, target_triple, + "abi-checker not supported on cross-compilation scenarios" + ); + + eprintln!("Building sysroot for abi-checker"); + build_sysroot::build_sysroot( + channel, + sysroot_kind, + target_dir, + cg_clif_build_dir, + host_triple, + target_triple, + ); + + eprintln!("Running abi-checker"); + let mut abi_checker_path = env::current_dir().unwrap(); + abi_checker_path.push("abi-checker"); + env::set_current_dir(abi_checker_path.clone()).unwrap(); + + let build_dir = abi_checker_path.parent().unwrap().join("build"); + let cg_clif_dylib_path = build_dir.join(if cfg!(windows) { "bin" } else { "lib" }).join( + env::consts::DLL_PREFIX.to_string() + "rustc_codegen_cranelift" + env::consts::DLL_SUFFIX, + ); + println!("cg_clif_dylib_path: {}", cg_clif_dylib_path.display()); + + let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"]; + + for pair in pairs { + eprintln!("[ABI-CHECKER] Running pair {pair}"); + + let mut cmd = Command::new("cargo"); + cmd.arg("run"); + cmd.arg("--target"); + cmd.arg(target_triple); + cmd.arg("--"); + cmd.arg("--pairs"); + cmd.arg(pair); + cmd.arg("--add-rustc-codegen-backend"); + cmd.arg(format!("cgclif:{}", cg_clif_dylib_path.display())); + + let output = spawn_and_wait_with_input(cmd, "".to_string()); + + // TODO: The correct thing to do here is to check the exit code, but abi-checker + // currently doesn't return 0 on success, so check for the test fail count. + // See: https://github.com/Gankra/abi-checker/issues/10 + let failed = !(output.contains("0 failed") && output.contains("0 completely failed")); + if failed { + panic!("abi-checker for pair {} failed!", pair); + } + } +} diff --git a/build_system/mod.rs b/build_system/mod.rs index 88c4150dbba..c5b3e6619b7 100644 --- a/build_system/mod.rs +++ b/build_system/mod.rs @@ -4,6 +4,7 @@ use std::process; use self::utils::is_ci; +mod abi_checker; mod build_backend; mod build_sysroot; mod config; @@ -21,6 +22,9 @@ fn usage() { eprintln!( " ./y.rs test [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]" ); + eprintln!( + " ./y.rs abi-checker [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]" + ); } macro_rules! arg_error { @@ -35,6 +39,7 @@ macro_rules! arg_error { enum Command { Build, Test, + AbiChecker, } #[derive(Copy, Clone, Debug)] @@ -66,6 +71,7 @@ pub fn main() { } Some("build") => Command::Build, Some("test") => Command::Test, + Some("abi-checker") => Command::AbiChecker, Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), Some(command) => arg_error!("Unknown command {}", command), None => { @@ -152,5 +158,15 @@ pub fn main() { &target_triple, ); } + Command::AbiChecker => { + abi_checker::run( + channel, + sysroot_kind, + &target_dir, + &cg_clif_build_dir, + &host_triple, + &target_triple, + ); + } } } diff --git a/build_system/prepare.rs b/build_system/prepare.rs index 7e0fd182d98..12aafdc1fb3 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -14,6 +14,13 @@ pub(crate) fn prepare() { eprintln!("[INSTALL] hyperfine"); Command::new("cargo").arg("install").arg("hyperfine").spawn().unwrap().wait().unwrap(); + clone_repo_shallow_github( + "abi-checker", + "Gankra", + "abi-checker", + "7c1571da6e43f9a37347623e7d5c7d51be664a7b", + ); + clone_repo_shallow_github( "rand", "rust-random", -- cgit 1.4.1-3-g733a5 From fb6362e093eca9ad754327b0134aaee3cb3864c3 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 6 Aug 2022 15:59:45 +0100 Subject: Test adding abi-checker to CI --- .github/workflows/main.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e8897e9ae81..0b259369e61 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -105,6 +105,11 @@ jobs: ./y.rs test + + - name: Run abi-checker + if: matrix.env.TARGET_TRIPLE == '' + run: ./y.rs abi-checker + - name: Package prebuilt cg_clif run: tar cvfJ cg_clif.tar.xz build -- cgit 1.4.1-3-g733a5 From 569312278f1d38cd5634d4fd6fa1beef6ded69e2 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 6 Aug 2022 20:51:20 +0100 Subject: Add abi-checker to clean_all.sh --- clean_all.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clean_all.sh b/clean_all.sh index ea1f8c1e892..62e52bd1958 100755 --- a/clean_all.sh +++ b/clean_all.sh @@ -3,4 +3,4 @@ set -e rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version} rm -rf target/ build/ perf.data{,.old} y.bin -rm -rf rand/ regex/ simple-raytracer/ portable-simd/ +rm -rf rand/ regex/ simple-raytracer/ portable-simd/ abi-checker/ -- cgit 1.4.1-3-g733a5 From e5ba71a71b79525fdd649624af63fc8770f90835 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 6 Aug 2022 20:51:47 +0100 Subject: Pass all pairs to abi-checker --- build_system/abi_checker.rs | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/build_system/abi_checker.rs b/build_system/abi_checker.rs index 1aff4acc21b..21d9afc8231 100644 --- a/build_system/abi_checker.rs +++ b/build_system/abi_checker.rs @@ -37,31 +37,26 @@ pub(crate) fn run( let cg_clif_dylib_path = build_dir.join(if cfg!(windows) { "bin" } else { "lib" }).join( env::consts::DLL_PREFIX.to_string() + "rustc_codegen_cranelift" + env::consts::DLL_SUFFIX, ); - println!("cg_clif_dylib_path: {}", cg_clif_dylib_path.display()); let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"]; - for pair in pairs { - eprintln!("[ABI-CHECKER] Running pair {pair}"); - - let mut cmd = Command::new("cargo"); - cmd.arg("run"); - cmd.arg("--target"); - cmd.arg(target_triple); - cmd.arg("--"); - cmd.arg("--pairs"); - cmd.arg(pair); - cmd.arg("--add-rustc-codegen-backend"); - cmd.arg(format!("cgclif:{}", cg_clif_dylib_path.display())); - - let output = spawn_and_wait_with_input(cmd, "".to_string()); - - // TODO: The correct thing to do here is to check the exit code, but abi-checker - // currently doesn't return 0 on success, so check for the test fail count. - // See: https://github.com/Gankra/abi-checker/issues/10 - let failed = !(output.contains("0 failed") && output.contains("0 completely failed")); - if failed { - panic!("abi-checker for pair {} failed!", pair); - } + let mut cmd = Command::new("cargo"); + cmd.arg("run"); + cmd.arg("--target"); + cmd.arg(target_triple); + cmd.arg("--"); + cmd.arg("--pairs"); + cmd.args(pairs); + cmd.arg("--add-rustc-codegen-backend"); + cmd.arg(format!("cgclif:{}", cg_clif_dylib_path.display())); + + let output = spawn_and_wait_with_input(cmd, "".to_string()); + + // TODO: The correct thing to do here is to check the exit code, but abi-checker + // currently doesn't return 0 on success, so check for the test fail count. + // See: https://github.com/Gankra/abi-checker/issues/10 + let failed = !(output.contains("0 failed") && output.contains("0 completely failed")); + if failed { + panic!("abi-checker failed!"); } } -- cgit 1.4.1-3-g733a5 From 7610be478f9e67a4e0e13cddb50f171e82cc3170 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 6 Aug 2022 21:24:38 +0100 Subject: Move abi-checker to y.rs test --- .github/workflows/main.yml | 5 ----- build_system/abi_checker.rs | 14 ++++++++++---- build_system/mod.rs | 14 ++++---------- config.txt | 2 ++ 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0b259369e61..e8897e9ae81 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -105,11 +105,6 @@ jobs: ./y.rs test - - - name: Run abi-checker - if: matrix.env.TARGET_TRIPLE == '' - run: ./y.rs abi-checker - - name: Package prebuilt cg_clif run: tar cvfJ cg_clif.tar.xz build diff --git a/build_system/abi_checker.rs b/build_system/abi_checker.rs index 21d9afc8231..b6dc0fa6922 100644 --- a/build_system/abi_checker.rs +++ b/build_system/abi_checker.rs @@ -1,4 +1,5 @@ use super::build_sysroot; +use super::config; use super::utils::spawn_and_wait_with_input; use build_system::SysrootKind; use std::env; @@ -13,10 +14,15 @@ pub(crate) fn run( host_triple: &str, target_triple: &str, ) { - assert_eq!( - host_triple, target_triple, - "abi-checker not supported on cross-compilation scenarios" - ); + if !config::get_bool("testsuite.abi-checker") { + eprintln!("[SKIP] abi-checker"); + return; + } + + if host_triple != target_triple { + eprintln!("[SKIP] abi-checker (cross-compilation not supported)"); + return; + } eprintln!("Building sysroot for abi-checker"); build_sysroot::build_sysroot( diff --git a/build_system/mod.rs b/build_system/mod.rs index c5b3e6619b7..c3706dc6f82 100644 --- a/build_system/mod.rs +++ b/build_system/mod.rs @@ -22,9 +22,6 @@ fn usage() { eprintln!( " ./y.rs test [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]" ); - eprintln!( - " ./y.rs abi-checker [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]" - ); } macro_rules! arg_error { @@ -39,7 +36,6 @@ macro_rules! arg_error { enum Command { Build, Test, - AbiChecker, } #[derive(Copy, Clone, Debug)] @@ -71,7 +67,6 @@ pub fn main() { } Some("build") => Command::Build, Some("test") => Command::Test, - Some("abi-checker") => Command::AbiChecker, Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), Some(command) => arg_error!("Unknown command {}", command), None => { @@ -147,9 +142,8 @@ pub fn main() { &host_triple, &target_triple, ); - } - Command::Build => { - build_sysroot::build_sysroot( + + abi_checker::run( channel, sysroot_kind, &target_dir, @@ -158,8 +152,8 @@ pub fn main() { &target_triple, ); } - Command::AbiChecker => { - abi_checker::run( + Command::Build => { + build_sysroot::build_sysroot( channel, sysroot_kind, &target_dir, diff --git a/config.txt b/config.txt index 5e4d230776d..2264d301d59 100644 --- a/config.txt +++ b/config.txt @@ -48,3 +48,5 @@ test.libcore test.regex-shootout-regex-dna test.regex test.portable-simd + +testsuite.abi-checker -- cgit 1.4.1-3-g733a5 From f20ceb1c6fd7fa29a91677be548d6f8ca6c4b172 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 6 Aug 2022 22:33:06 +0200 Subject: Encode index of SourceFile along with span. --- compiler/rustc_metadata/src/rmeta/decoder.rs | 33 ++++------ compiler/rustc_metadata/src/rmeta/encoder.rs | 96 ++++++++++++++-------------- compiler/rustc_span/src/lib.rs | 2 + compiler/rustc_span/src/source_map.rs | 2 + compiler/rustc_span/src/source_map/tests.rs | 1 + 5 files changed, 65 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 40dc4fb052d..444b5884187 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -527,6 +527,9 @@ impl<'a, 'tcx> Decodable> for Span { bug!("Cannot decode Span without Session.") }; + // Index of the file in the corresponding crate's list of encoded files. + let metadata_index = usize::decode(decoder); + // There are two possibilities here: // 1. This is a 'local span', which is located inside a `SourceFile` // that came from this crate. In this case, we use the source map data @@ -587,27 +590,9 @@ impl<'a, 'tcx> Decodable> for Span { foreign_data.imported_source_files(sess) }; - let source_file = { - // Optimize for the case that most spans within a translated item - // originate from the same source_file. - let last_source_file = &imported_source_files[decoder.last_source_file_index]; - - if lo >= last_source_file.original_start_pos && lo <= last_source_file.original_end_pos - { - last_source_file - } else { - let index = imported_source_files - .binary_search_by_key(&lo, |source_file| source_file.original_start_pos) - .unwrap_or_else(|index| index - 1); - - // Don't try to cache the index for foreign spans, - // as this would require a map from CrateNums to indices - if tag == TAG_VALID_SPAN_LOCAL { - decoder.last_source_file_index = index; - } - &imported_source_files[index] - } - }; + // Optimize for the case that most spans within a translated item + // originate from the same source_file. + let source_file = &imported_source_files[metadata_index]; // Make sure our binary search above is correct. debug_assert!( @@ -1545,7 +1530,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { let external_source_map = self.root.source_map.decode(self); external_source_map - .map(|source_file_to_import| { + .enumerate() + .map(|(source_file_index, source_file_to_import)| { // We can't reuse an existing SourceFile, so allocate a new one // containing the information we need. let rustc_span::SourceFile { @@ -1605,6 +1591,9 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { normalized_pos, start_pos, end_pos, + source_file_index + .try_into() + .expect("cannot import more than U32_MAX files"), ); debug!( "CrateMetaData::imported_source_files alloc \ diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 33278367ce3..de78ab41f05 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -17,7 +17,6 @@ use rustc_hir::definitions::DefPathData; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::lang_items; use rustc_hir::{AnonConst, GenericParamKind}; -use rustc_index::bit_set::GrowableBitSet; use rustc_middle::hir::nested_filter; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::{ @@ -66,13 +65,10 @@ pub(super) struct EncodeContext<'a, 'tcx> { // The indices (into the `SourceMap`'s `MonotonicVec`) // of all of the `SourceFiles` that we need to serialize. // When we serialize a `Span`, we insert the index of its - // `SourceFile` into the `GrowableBitSet`. - // - // This needs to be a `GrowableBitSet` and not a - // regular `BitSet` because we may actually import new `SourceFiles` - // during metadata encoding, due to executing a query - // with a result containing a foreign `Span`. - required_source_files: Option>, + // `SourceFile` into the `FxIndexSet`. + // The order inside the `FxIndexSet` is used as on-disk + // order of `SourceFiles`, and encoded inside `Span`s. + required_source_files: Option>, is_proc_macro: bool, hygiene_ctxt: &'a HygieneEncodeContext, } @@ -245,10 +241,6 @@ impl<'a, 'tcx> Encodable> for Span { return TAG_PARTIAL_SPAN.encode(s); } - let source_files = s.required_source_files.as_mut().expect("Already encoded SourceMap!"); - // Record the fact that we need to encode the data for this `SourceFile` - source_files.insert(s.source_file_cache.1); - // There are two possible cases here: // 1. This span comes from a 'foreign' crate - e.g. some crate upstream of the // crate we are writing metadata for. When the metadata for *this* crate gets @@ -265,30 +257,38 @@ impl<'a, 'tcx> Encodable> for Span { // if we're a proc-macro crate. // This allows us to avoid loading the dependencies of proc-macro crates: all of // the information we need to decode `Span`s is stored in the proc-macro crate. - let (tag, lo, hi) = if s.source_file_cache.0.is_imported() && !s.is_proc_macro { - // To simplify deserialization, we 'rebase' this span onto the crate it originally came from - // (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values - // are relative to the source map information for the 'foreign' crate whose CrateNum - // we write into the metadata. This allows `imported_source_files` to binary - // search through the 'foreign' crate's source map information, using the - // deserialized 'lo' and 'hi' values directly. - // - // All of this logic ensures that the final result of deserialization is a 'normal' - // Span that can be used without any additional trouble. - let external_start_pos = { - // Introduce a new scope so that we drop the 'lock()' temporary - match &*s.source_file_cache.0.external_src.lock() { - ExternalSource::Foreign { original_start_pos, .. } => *original_start_pos, - src => panic!("Unexpected external source {:?}", src), - } - }; - let lo = (span.lo - s.source_file_cache.0.start_pos) + external_start_pos; - let hi = (span.hi - s.source_file_cache.0.start_pos) + external_start_pos; + let (tag, lo, hi, metadata_index) = + if s.source_file_cache.0.is_imported() && !s.is_proc_macro { + // To simplify deserialization, we 'rebase' this span onto the crate it originally came from + // (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values + // are relative to the source map information for the 'foreign' crate whose CrateNum + // we write into the metadata. This allows `imported_source_files` to binary + // search through the 'foreign' crate's source map information, using the + // deserialized 'lo' and 'hi' values directly. + // + // All of this logic ensures that the final result of deserialization is a 'normal' + // Span that can be used without any additional trouble. + let (external_start_pos, metadata_index) = { + // Introduce a new scope so that we drop the 'lock()' temporary + match &*s.source_file_cache.0.external_src.lock() { + ExternalSource::Foreign { original_start_pos, metadata_index, .. } => { + (*original_start_pos, *metadata_index as usize) + } + src => panic!("Unexpected external source {:?}", src), + } + }; + let lo = (span.lo - s.source_file_cache.0.start_pos) + external_start_pos; + let hi = (span.hi - s.source_file_cache.0.start_pos) + external_start_pos; - (TAG_VALID_SPAN_FOREIGN, lo, hi) - } else { - (TAG_VALID_SPAN_LOCAL, span.lo, span.hi) - }; + (TAG_VALID_SPAN_FOREIGN, lo, hi, metadata_index) + } else { + // Record the fact that we need to encode the data for this `SourceFile` + let source_files = + s.required_source_files.as_mut().expect("Already encoded SourceMap!"); + let (source_file_index, _) = source_files.insert_full(s.source_file_cache.1); + + (TAG_VALID_SPAN_LOCAL, span.lo, span.hi, source_file_index) + }; tag.encode(s); lo.encode(s); @@ -298,6 +298,9 @@ impl<'a, 'tcx> Encodable> for Span { let len = hi - lo; len.encode(s); + // Encode the index of the `SourceFile` for the span, in order to make decoding faster. + metadata_index.encode(s); + if tag == TAG_VALID_SPAN_FOREIGN { // This needs to be two lines to avoid holding the `s.source_file_cache` // while calling `cnum.encode(s)` @@ -460,18 +463,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let working_directory = &self.tcx.sess.opts.working_dir; - let adapted = all_source_files + // Only serialize `SourceFile`s that were used during the encoding of a `Span`. + // + // The order in which we encode source files is important here: the on-disk format for + // `Span` contains the index of the corresponding `SourceFile`. + let adapted = required_source_files .iter() - .enumerate() - .filter(|(idx, source_file)| { - // Only serialize `SourceFile`s that were used - // during the encoding of a `Span` - required_source_files.contains(*idx) && - // Don't serialize imported `SourceFile`s, unless - // we're in a proc-macro crate. - (!source_file.is_imported() || self.is_proc_macro) - }) - .map(|(_, source_file)| { + .map(|&source_file_index| &all_source_files[source_file_index]) + .map(|source_file| { + // Don't serialize imported `SourceFile`s, unless we're in a proc-macro crate. + assert!(!source_file.is_imported() || self.is_proc_macro); + // At export time we expand all source file paths to absolute paths because // downstream compilation sessions can have a different compiler working // directory, so relative paths from this or any other upstream crate @@ -2228,7 +2230,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) { let source_map_files = tcx.sess.source_map().files(); let source_file_cache = (source_map_files[0].clone(), 0); - let required_source_files = Some(GrowableBitSet::with_capacity(source_map_files.len())); + let required_source_files = Some(FxIndexSet::default()); drop(source_map_files); let hygiene_ctxt = HygieneEncodeContext::default(); diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index cf306928151..bae05f2f02e 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1098,6 +1098,8 @@ pub enum ExternalSource { original_start_pos: BytePos, /// The end of this SourceFile within the source_map of its original crate. original_end_pos: BytePos, + /// Index of the file inside metadata. + metadata_index: u32, }, } diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 28381157d50..387777f7af6 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -337,6 +337,7 @@ impl SourceMap { mut file_local_normalized_pos: Vec, original_start_pos: BytePos, original_end_pos: BytePos, + metadata_index: u32, ) -> Lrc { let start_pos = self .allocate_address_space(source_len) @@ -383,6 +384,7 @@ impl SourceMap { kind: ExternalSourceKind::AbsentOk, original_start_pos, original_end_pos, + metadata_index, }), start_pos, end_pos, diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs index be827cea874..2cada019b7f 100644 --- a/compiler/rustc_span/src/source_map/tests.rs +++ b/compiler/rustc_span/src/source_map/tests.rs @@ -252,6 +252,7 @@ fn t10() { normalized_pos, start_pos, end_pos, + 0, ); assert!( -- cgit 1.4.1-3-g733a5 From a09e9c99a4c58ab6208aa44c4061df9aa2e40197 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 6 Aug 2022 23:00:49 +0200 Subject: Decode SourceFile out of order. --- compiler/rustc_metadata/src/rmeta/decoder.rs | 187 +++++++++++---------- .../src/rmeta/decoder/cstore_impl.rs | 5 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 109 ++++++------ compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- 4 files changed, 154 insertions(+), 149 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 444b5884187..29acacbf3b3 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -37,6 +37,7 @@ use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{self, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP}; use proc_macro::bridge::client::ProcMacro; +use std::cell::RefCell; use std::io; use std::iter::TrustedLen; use std::mem; @@ -99,7 +100,7 @@ pub(crate) struct CrateMetadata { /// Proc macro descriptions for this crate, if it's a proc macro crate. raw_proc_macros: Option<&'static [ProcMacro]>, /// Source maps for code from the crate. - source_map_import_info: OnceCell>, + source_map_import_info: RefCell>>, /// For every definition in this crate, maps its `DefPathHash` to its `DefIndex`. def_path_hash_map: DefPathHashMapRef<'static>, /// Likewise for ExpnHash. @@ -143,7 +144,8 @@ pub(crate) struct CrateMetadata { } /// Holds information about a rustc_span::SourceFile imported from another crate. -/// See `imported_source_files()` for more information. +/// See `imported_source_file()` for more information. +#[derive(Clone)] struct ImportedSourceFile { /// This SourceFile's byte-offset within the source_map of its original crate original_start_pos: rustc_span::BytePos, @@ -528,7 +530,7 @@ impl<'a, 'tcx> Decodable> for Span { }; // Index of the file in the corresponding crate's list of encoded files. - let metadata_index = usize::decode(decoder); + let metadata_index = u32::decode(decoder); // There are two possibilities here: // 1. This is a 'local span', which is located inside a `SourceFile` @@ -556,10 +558,10 @@ impl<'a, 'tcx> Decodable> for Span { // to be based on the *foreign* crate (e.g. crate C), not the crate // we are writing metadata for (e.g. crate B). This allows us to // treat the 'local' and 'foreign' cases almost identically during deserialization: - // we can call `imported_source_files` for the proper crate, and binary search + // we can call `imported_source_file` for the proper crate, and binary search // through the returned slice using our span. - let imported_source_files = if tag == TAG_VALID_SPAN_LOCAL { - decoder.cdata().imported_source_files(sess) + let source_file = if tag == TAG_VALID_SPAN_LOCAL { + decoder.cdata().imported_source_file(metadata_index, sess) } else { // When we encode a proc-macro crate, all `Span`s should be encoded // with `TAG_VALID_SPAN_LOCAL` @@ -587,13 +589,9 @@ impl<'a, 'tcx> Decodable> for Span { decoder.last_source_file_index = 0; let foreign_data = decoder.cdata().cstore.get_crate_data(cnum); - foreign_data.imported_source_files(sess) + foreign_data.imported_source_file(metadata_index, sess) }; - // Optimize for the case that most spans within a translated item - // originate from the same source_file. - let source_file = &imported_source_files[metadata_index]; - // Make sure our binary search above is correct. debug_assert!( lo >= source_file.original_start_pos && lo <= source_file.original_end_pos, @@ -1438,7 +1436,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { /// /// Proc macro crates don't currently export spans, so this function does not have /// to work for them. - fn imported_source_files(self, sess: &Session) -> &'a [ImportedSourceFile] { + fn imported_source_file(self, source_file_index: u32, sess: &Session) -> ImportedSourceFile { fn filter<'a>(sess: &Session, path: Option<&'a Path>) -> Option<&'a Path> { path.filter(|_| { // Only spend time on further checks if we have what to translate *to*. @@ -1526,94 +1524,97 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } }; - self.cdata.source_map_import_info.get_or_init(|| { - let external_source_map = self.root.source_map.decode(self); - - external_source_map - .enumerate() - .map(|(source_file_index, source_file_to_import)| { - // We can't reuse an existing SourceFile, so allocate a new one - // containing the information we need. - let rustc_span::SourceFile { - mut name, - src_hash, - start_pos, - end_pos, - lines, - multibyte_chars, - non_narrow_chars, - normalized_pos, - name_hash, - .. - } = source_file_to_import; - - // If this file is under $sysroot/lib/rustlib/src/ but has not been remapped - // during rust bootstrapping by `remap-debuginfo = true`, and the user - // wish to simulate that behaviour by -Z simulate-remapped-rust-src-base, - // then we change `name` to a similar state as if the rust was bootstrapped - // with `remap-debuginfo = true`. - // This is useful for testing so that tests about the effects of - // `try_to_translate_virtual_to_real` don't have to worry about how the - // compiler is bootstrapped. - if let Some(virtual_dir) = - &sess.opts.unstable_opts.simulate_remapped_rust_src_base - { - if let Some(real_dir) = &sess.opts.real_rust_source_base_dir { - if let rustc_span::FileName::Real(ref mut old_name) = name { - if let rustc_span::RealFileName::LocalPath(local) = old_name { - if let Ok(rest) = local.strip_prefix(real_dir) { - *old_name = rustc_span::RealFileName::Remapped { - local_path: None, - virtual_name: virtual_dir.join(rest), - }; - } + let mut import_info = self.cdata.source_map_import_info.borrow_mut(); + for _ in import_info.len()..=(source_file_index as usize) { + import_info.push(None); + } + import_info[source_file_index as usize] + .get_or_insert_with(|| { + let source_file_to_import = self + .root + .source_map + .get(self, source_file_index) + .expect("missing source file") + .decode(self); + + // We can't reuse an existing SourceFile, so allocate a new one + // containing the information we need. + let rustc_span::SourceFile { + mut name, + src_hash, + start_pos, + end_pos, + lines, + multibyte_chars, + non_narrow_chars, + normalized_pos, + name_hash, + .. + } = source_file_to_import; + + // If this file is under $sysroot/lib/rustlib/src/ but has not been remapped + // during rust bootstrapping by `remap-debuginfo = true`, and the user + // wish to simulate that behaviour by -Z simulate-remapped-rust-src-base, + // then we change `name` to a similar state as if the rust was bootstrapped + // with `remap-debuginfo = true`. + // This is useful for testing so that tests about the effects of + // `try_to_translate_virtual_to_real` don't have to worry about how the + // compiler is bootstrapped. + if let Some(virtual_dir) = &sess.opts.unstable_opts.simulate_remapped_rust_src_base + { + if let Some(real_dir) = &sess.opts.real_rust_source_base_dir { + if let rustc_span::FileName::Real(ref mut old_name) = name { + if let rustc_span::RealFileName::LocalPath(local) = old_name { + if let Ok(rest) = local.strip_prefix(real_dir) { + *old_name = rustc_span::RealFileName::Remapped { + local_path: None, + virtual_name: virtual_dir.join(rest), + }; } } } } + } - // If this file's path has been remapped to `/rustc/$hash`, - // we might be able to reverse that (also see comments above, - // on `try_to_translate_virtual_to_real`). - try_to_translate_virtual_to_real(&mut name); - - let source_length = (end_pos - start_pos).to_usize(); - - let local_version = sess.source_map().new_imported_source_file( - name, - src_hash, - name_hash, - source_length, - self.cnum, - lines, - multibyte_chars, - non_narrow_chars, - normalized_pos, - start_pos, - end_pos, - source_file_index - .try_into() - .expect("cannot import more than U32_MAX files"), - ); - debug!( - "CrateMetaData::imported_source_files alloc \ + // If this file's path has been remapped to `/rustc/$hash`, + // we might be able to reverse that (also see comments above, + // on `try_to_translate_virtual_to_real`). + try_to_translate_virtual_to_real(&mut name); + + let source_length = (end_pos - start_pos).to_usize(); + + let local_version = sess.source_map().new_imported_source_file( + name, + src_hash, + name_hash, + source_length, + self.cnum, + lines, + multibyte_chars, + non_narrow_chars, + normalized_pos, + start_pos, + end_pos, + source_file_index, + ); + debug!( + "CrateMetaData::imported_source_files alloc \ source_file {:?} original (start_pos {:?} end_pos {:?}) \ translated (start_pos {:?} end_pos {:?})", - local_version.name, - start_pos, - end_pos, - local_version.start_pos, - local_version.end_pos - ); + local_version.name, + start_pos, + end_pos, + local_version.start_pos, + local_version.end_pos + ); - ImportedSourceFile { - original_start_pos: start_pos, - original_end_pos: end_pos, - translated_source_file: local_version, - } - }) - .collect() - }) + ImportedSourceFile { + original_start_pos: start_pos, + original_end_pos: end_pos, + translated_source_file: local_version, + } + }) + .clone() } fn get_generator_diagnostic_data( @@ -1676,7 +1677,7 @@ impl CrateMetadata { trait_impls, incoherent_impls: Default::default(), raw_proc_macros, - source_map_import_info: OnceCell::new(), + source_map_import_info: RefCell::new(Vec::new()), def_path_hash_map, expn_hash_map: Default::default(), alloc_decoding_state, diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 38ce50e8323..8b4220d4492 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -675,6 +675,9 @@ impl CrateStore for CStore { } fn import_source_files(&self, sess: &Session, cnum: CrateNum) { - self.get_crate_data(cnum).imported_source_files(sess); + let cdata = self.get_crate_data(cnum); + for file_index in 0..cdata.root.source_map.size() { + cdata.imported_source_file(file_index as u32, sess); + } } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index de78ab41f05..576875f08c2 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -272,7 +272,7 @@ impl<'a, 'tcx> Encodable> for Span { // Introduce a new scope so that we drop the 'lock()' temporary match &*s.source_file_cache.0.external_src.lock() { ExternalSource::Foreign { original_start_pos, metadata_index, .. } => { - (*original_start_pos, *metadata_index as usize) + (*original_start_pos, *metadata_index) } src => panic!("Unexpected external source {:?}", src), } @@ -286,6 +286,8 @@ impl<'a, 'tcx> Encodable> for Span { let source_files = s.required_source_files.as_mut().expect("Already encoded SourceMap!"); let (source_file_index, _) = source_files.insert_full(s.source_file_cache.1); + let source_file_index: u32 = + source_file_index.try_into().expect("cannot export more than U32_MAX files"); (TAG_VALID_SPAN_LOCAL, span.lo, span.hi, source_file_index) }; @@ -452,7 +454,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.lazy(DefPathHashMapRef::BorrowedFromTcx(self.tcx.def_path_hash_to_def_index_map())) } - fn encode_source_map(&mut self) -> LazyArray { + fn encode_source_map(&mut self) -> LazyTable> { let source_map = self.tcx.sess.source_map(); let all_source_files = source_map.files(); @@ -463,65 +465,64 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let working_directory = &self.tcx.sess.opts.working_dir; + let mut adapted = TableBuilder::default(); + // Only serialize `SourceFile`s that were used during the encoding of a `Span`. // // The order in which we encode source files is important here: the on-disk format for // `Span` contains the index of the corresponding `SourceFile`. - let adapted = required_source_files - .iter() - .map(|&source_file_index| &all_source_files[source_file_index]) - .map(|source_file| { - // Don't serialize imported `SourceFile`s, unless we're in a proc-macro crate. - assert!(!source_file.is_imported() || self.is_proc_macro); - - // At export time we expand all source file paths to absolute paths because - // downstream compilation sessions can have a different compiler working - // directory, so relative paths from this or any other upstream crate - // won't be valid anymore. - // - // At this point we also erase the actual on-disk path and only keep - // the remapped version -- as is necessary for reproducible builds. - match source_file.name { - FileName::Real(ref original_file_name) => { - let adapted_file_name = - source_map.path_mapping().to_embeddable_absolute_path( - original_file_name.clone(), - working_directory, - ); - - if adapted_file_name != *original_file_name { - let mut adapted: SourceFile = (**source_file).clone(); - adapted.name = FileName::Real(adapted_file_name); - adapted.name_hash = { - let mut hasher: StableHasher = StableHasher::new(); - adapted.name.hash(&mut hasher); - hasher.finish::() - }; - Lrc::new(adapted) - } else { - // Nothing to adapt - source_file.clone() - } + for (on_disk_index, &source_file_index) in required_source_files.iter().enumerate() { + let source_file = &all_source_files[source_file_index]; + // Don't serialize imported `SourceFile`s, unless we're in a proc-macro crate. + assert!(!source_file.is_imported() || self.is_proc_macro); + + // At export time we expand all source file paths to absolute paths because + // downstream compilation sessions can have a different compiler working + // directory, so relative paths from this or any other upstream crate + // won't be valid anymore. + // + // At this point we also erase the actual on-disk path and only keep + // the remapped version -- as is necessary for reproducible builds. + let mut source_file = match source_file.name { + FileName::Real(ref original_file_name) => { + let adapted_file_name = source_map + .path_mapping() + .to_embeddable_absolute_path(original_file_name.clone(), working_directory); + + if adapted_file_name != *original_file_name { + let mut adapted: SourceFile = (**source_file).clone(); + adapted.name = FileName::Real(adapted_file_name); + adapted.name_hash = { + let mut hasher: StableHasher = StableHasher::new(); + adapted.name.hash(&mut hasher); + hasher.finish::() + }; + Lrc::new(adapted) + } else { + // Nothing to adapt + source_file.clone() } - // expanded code, not from a file - _ => source_file.clone(), } - }) - .map(|mut source_file| { - // We're serializing this `SourceFile` into our crate metadata, - // so mark it as coming from this crate. - // This also ensures that we don't try to deserialize the - // `CrateNum` for a proc-macro dependency - since proc macro - // dependencies aren't loaded when we deserialize a proc-macro, - // trying to remap the `CrateNum` would fail. - if self.is_proc_macro { - Lrc::make_mut(&mut source_file).cnum = LOCAL_CRATE; - } - source_file - }) - .collect::>(); + // expanded code, not from a file + _ => source_file.clone(), + }; + + // We're serializing this `SourceFile` into our crate metadata, + // so mark it as coming from this crate. + // This also ensures that we don't try to deserialize the + // `CrateNum` for a proc-macro dependency - since proc macro + // dependencies aren't loaded when we deserialize a proc-macro, + // trying to remap the `CrateNum` would fail. + if self.is_proc_macro { + Lrc::make_mut(&mut source_file).cnum = LOCAL_CRATE; + } + + let on_disk_index: u32 = + on_disk_index.try_into().expect("cannot export more than U32_MAX files"); + adapted.set(on_disk_index, self.lazy(source_file)); + } - self.lazy_array(adapted.iter().map(|rc| &**rc)) + adapted.encode(&mut self.opaque) } fn encode_crate_root(&mut self) -> LazyValue { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 66bdecc30db..7a39f4d4e6b 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -249,7 +249,7 @@ pub(crate) struct CrateRoot { def_path_hash_map: LazyValue>, - source_map: LazyArray, + source_map: LazyTable>, compiler_builtins: bool, needs_allocator: bool, -- cgit 1.4.1-3-g733a5 From d74af405eb349922e7aca4ecc510991bb5ae9ab4 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 6 Aug 2022 23:09:15 +0200 Subject: Remove unused cache. --- compiler/rustc_metadata/src/rmeta/decoder.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 29acacbf3b3..be5c7669b01 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -162,9 +162,6 @@ pub(super) struct DecodeContext<'a, 'tcx> { sess: Option<&'tcx Session>, tcx: Option>, - // Cache the last used source_file for translating spans as an optimization. - last_source_file_index: usize, - lazy_state: LazyState, // Used for decoding interpret::AllocIds in a cached & thread-safe manner. @@ -193,7 +190,6 @@ pub(super) trait Metadata<'a, 'tcx>: Copy { blob: self.blob(), sess: self.sess().or(tcx.map(|tcx| tcx.sess)), tcx, - last_source_file_index: 0, lazy_state: LazyState::NoNode, alloc_decoding_session: self .cdata() @@ -582,12 +578,6 @@ impl<'a, 'tcx> Decodable> for Span { cnum ); - // Decoding 'foreign' spans should be rare enough that it's - // not worth it to maintain a per-CrateNum cache for `last_source_file_index`. - // We just set it to 0, to ensure that we don't try to access something out - // of bounds for our initial 'guess' - decoder.last_source_file_index = 0; - let foreign_data = decoder.cdata().cstore.get_crate_data(cnum); foreign_data.imported_source_file(metadata_index, sess) }; -- cgit 1.4.1-3-g733a5 From 7c2d722fb0b9ef5e0a2c3db8a8e35789f6ff8dc2 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 6 Aug 2022 23:13:09 +0200 Subject: Simplify encoding a bit. --- compiler/rustc_metadata/src/rmeta/encoder.rs | 69 ++++++++++++++-------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 576875f08c2..463cfece715 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -234,13 +234,17 @@ impl<'a, 'tcx> Encodable> for Span { s.source_file_cache = (source_map.files()[source_file_index].clone(), source_file_index); } + let (ref source_file, source_file_index) = s.source_file_cache; - if !s.source_file_cache.0.contains(span.hi) { + if !source_file.contains(span.hi) { // Unfortunately, macro expansion still sometimes generates Spans // that malformed in this way. return TAG_PARTIAL_SPAN.encode(s); } + // Length is independent of the span provenance. + let len = span.hi - span.lo; + // There are two possible cases here: // 1. This span comes from a 'foreign' crate - e.g. some crate upstream of the // crate we are writing metadata for. When the metadata for *this* crate gets @@ -257,47 +261,44 @@ impl<'a, 'tcx> Encodable> for Span { // if we're a proc-macro crate. // This allows us to avoid loading the dependencies of proc-macro crates: all of // the information we need to decode `Span`s is stored in the proc-macro crate. - let (tag, lo, hi, metadata_index) = - if s.source_file_cache.0.is_imported() && !s.is_proc_macro { - // To simplify deserialization, we 'rebase' this span onto the crate it originally came from - // (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values - // are relative to the source map information for the 'foreign' crate whose CrateNum - // we write into the metadata. This allows `imported_source_files` to binary - // search through the 'foreign' crate's source map information, using the - // deserialized 'lo' and 'hi' values directly. - // - // All of this logic ensures that the final result of deserialization is a 'normal' - // Span that can be used without any additional trouble. - let (external_start_pos, metadata_index) = { - // Introduce a new scope so that we drop the 'lock()' temporary - match &*s.source_file_cache.0.external_src.lock() { - ExternalSource::Foreign { original_start_pos, metadata_index, .. } => { - (*original_start_pos, *metadata_index) - } - src => panic!("Unexpected external source {:?}", src), + let (tag, lo, metadata_index) = if source_file.is_imported() && !s.is_proc_macro { + // To simplify deserialization, we 'rebase' this span onto the crate it originally came from + // (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values + // are relative to the source map information for the 'foreign' crate whose CrateNum + // we write into the metadata. This allows `imported_source_files` to binary + // search through the 'foreign' crate's source map information, using the + // deserialized 'lo' and 'hi' values directly. + // + // All of this logic ensures that the final result of deserialization is a 'normal' + // Span that can be used without any additional trouble. + let (external_start_pos, metadata_index) = { + // Introduce a new scope so that we drop the 'lock()' temporary + match &*source_file.external_src.lock() { + ExternalSource::Foreign { original_start_pos, metadata_index, .. } => { + (*original_start_pos, *metadata_index) } - }; - let lo = (span.lo - s.source_file_cache.0.start_pos) + external_start_pos; - let hi = (span.hi - s.source_file_cache.0.start_pos) + external_start_pos; - - (TAG_VALID_SPAN_FOREIGN, lo, hi, metadata_index) - } else { - // Record the fact that we need to encode the data for this `SourceFile` - let source_files = - s.required_source_files.as_mut().expect("Already encoded SourceMap!"); - let (source_file_index, _) = source_files.insert_full(s.source_file_cache.1); - let source_file_index: u32 = - source_file_index.try_into().expect("cannot export more than U32_MAX files"); - - (TAG_VALID_SPAN_LOCAL, span.lo, span.hi, source_file_index) + src => panic!("Unexpected external source {:?}", src), + } }; + let lo = (span.lo - source_file.start_pos) + external_start_pos; + + (TAG_VALID_SPAN_FOREIGN, lo, metadata_index) + } else { + // Record the fact that we need to encode the data for this `SourceFile` + let source_files = + s.required_source_files.as_mut().expect("Already encoded SourceMap!"); + let (metadata_index, _) = source_files.insert_full(source_file_index); + let metadata_index: u32 = + metadata_index.try_into().expect("cannot export more than U32_MAX files"); + + (TAG_VALID_SPAN_LOCAL, span.lo, metadata_index) + }; tag.encode(s); lo.encode(s); // Encode length which is usually less than span.hi and profits more // from the variable-length integer encoding that we use. - let len = hi - lo; len.encode(s); // Encode the index of the `SourceFile` for the span, in order to make decoding faster. -- cgit 1.4.1-3-g733a5 From 448c25599747a777ff23cbb5d419021d6994c5cb Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 6 Aug 2022 23:16:27 +0200 Subject: Bless ui tests. --- src/test/ui/issues/issue-31173.stderr | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index 68337a715e1..85ad950f389 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -18,16 +18,16 @@ error[E0599]: the method `collect` exists for struct `Cloned, [closure@$DIR/issue-31173.rs:6:39: 6:43]>>` due to unsatisfied trait bounds | - ::: $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL - | -LL | pub struct Cloned { - | -------------------- doesn't satisfy `_: Iterator` - | ::: $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL | LL | pub struct TakeWhile { | -------------------------- doesn't satisfy `<_ as Iterator>::Item = &_` | + ::: $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL + | +LL | pub struct Cloned { + | -------------------- doesn't satisfy `_: Iterator` + | = note: the following trait bounds were not satisfied: `, [closure@$DIR/issue-31173.rs:6:39: 6:43]> as Iterator>::Item = &_` which is required by `Cloned, [closure@$DIR/issue-31173.rs:6:39: 6:43]>>: Iterator` -- cgit 1.4.1-3-g733a5 From 16ba778c12e3303ab4d334c1c3dbfa5173248a80 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 6 Aug 2022 23:27:45 +0200 Subject: Support parallel compiler. --- compiler/rustc_metadata/src/rmeta/decoder.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index be5c7669b01..a58f6e6e1de 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -37,7 +37,6 @@ use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{self, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP}; use proc_macro::bridge::client::ProcMacro; -use std::cell::RefCell; use std::io; use std::iter::TrustedLen; use std::mem; @@ -100,7 +99,7 @@ pub(crate) struct CrateMetadata { /// Proc macro descriptions for this crate, if it's a proc macro crate. raw_proc_macros: Option<&'static [ProcMacro]>, /// Source maps for code from the crate. - source_map_import_info: RefCell>>, + source_map_import_info: Lock>>, /// For every definition in this crate, maps its `DefPathHash` to its `DefIndex`. def_path_hash_map: DefPathHashMapRef<'static>, /// Likewise for ExpnHash. @@ -1514,7 +1513,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } }; - let mut import_info = self.cdata.source_map_import_info.borrow_mut(); + let mut import_info = self.cdata.source_map_import_info.lock(); for _ in import_info.len()..=(source_file_index as usize) { import_info.push(None); } @@ -1667,7 +1666,7 @@ impl CrateMetadata { trait_impls, incoherent_impls: Default::default(), raw_proc_macros, - source_map_import_info: RefCell::new(Vec::new()), + source_map_import_info: Lock::new(Vec::new()), def_path_hash_map, expn_hash_map: Default::default(), alloc_decoding_state, -- cgit 1.4.1-3-g733a5 From 3c8563abcf91eda340aa77d238954dd00fa0cb34 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 6 Aug 2022 17:18:59 -0400 Subject: make NOP dyn casts not require anything about the vtable --- compiler/rustc_codegen_cranelift/src/unsize.rs | 1 + compiler/rustc_codegen_ssa/src/base.rs | 1 + compiler/rustc_const_eval/src/interpret/cast.rs | 7 +++++- .../ui/consts/const-eval/ub-wide-ptr.32bit.stderr | 26 +++++++++++++++------- .../ui/consts/const-eval/ub-wide-ptr.64bit.stderr | 26 +++++++++++++++------- src/test/ui/consts/const-eval/ub-wide-ptr.rs | 6 ++--- 6 files changed, 46 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs index 052ca0a082b..dd9d891ddbd 100644 --- a/compiler/rustc_codegen_cranelift/src/unsize.rs +++ b/compiler/rustc_codegen_cranelift/src/unsize.rs @@ -29,6 +29,7 @@ pub(crate) fn unsized_info<'tcx>( let old_info = old_info.expect("unsized_info: missing old info for trait upcasting coercion"); if data_a.principal_def_id() == data_b.principal_def_id() { + // A NOP cast that doesn't actually change anything, should be allowed even with invalid vtables. return old_info; } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index a840b270974..4c6be3f9108 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -151,6 +151,7 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let old_info = old_info.expect("unsized_info: missing old info for trait upcasting coercion"); if data_a.principal_def_id() == data_b.principal_def_id() { + // A NOP cast that doesn't actually change anything, should be allowed even with invalid vtables. return old_info; } diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index c97c31eb9da..14eb2a1537b 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -298,7 +298,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_immediate(val, dest) } (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => { - let (old_data, old_vptr) = self.read_immediate(src)?.to_scalar_pair()?; + let val = self.read_immediate(src)?; + if data_a.principal() == data_b.principal() { + // A NOP cast that doesn't actually change anything, should be allowed even with mismatching vtables. + return self.write_immediate(*val, dest); + } + let (old_data, old_vptr) = val.to_scalar_pair()?; let old_vptr = old_vptr.to_pointer(self)?; let (ty, old_trait) = self.get_ptr_vtable(old_vptr)?; if old_trait != data_a.principal() { diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr index 345ead48151..9431fb33c53 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr @@ -278,26 +278,36 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, ╾allocN─╼ ╾allocN─╼ │ ╾──╼╾──╼ } -error[E0080]: evaluation of constant value failed - --> $DIR/ub-wide-ptr.rs:147:62 +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:147:1 | LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾allocN─╼ 00 00 00 00 │ ╾──╼.... + } -error[E0080]: evaluation of constant value failed - --> $DIR/ub-wide-ptr.rs:150:65 +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:149:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾allocN─╼ ╾allocN─╼ │ ╾──╼╾──╼ + } error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:157:5 + --> $DIR/ub-wide-ptr.rs:155:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance) error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:161:5 + --> $DIR/ub-wide-ptr.rs:159:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr index 501932cb95c..15ef703024a 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr @@ -278,26 +278,36 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼ } -error[E0080]: evaluation of constant value failed - --> $DIR/ub-wide-ptr.rs:147:62 +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:147:1 | LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾──────allocN───────╼ 00 00 00 00 00 00 00 00 │ ╾──────╼........ + } -error[E0080]: evaluation of constant value failed - --> $DIR/ub-wide-ptr.rs:150:65 +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:149:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼ + } error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:157:5 + --> $DIR/ub-wide-ptr.rs:155:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance) error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:161:5 + --> $DIR/ub-wide-ptr.rs:159:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs index a0377ab1efd..2da694a8bc4 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -145,11 +145,9 @@ const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool // # raw trait object const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; -//~^ ERROR evaluation of constant value failed -//~| null pointer +//~^ ERROR it is undefined behavior to use this value const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; -//~^ ERROR evaluation of constant value failed -//~| does not point to a vtable +//~^ ERROR it is undefined behavior to use this value const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) } as *const dyn Trait; // ok because raw // Const eval fails for these, so they need to be statics to error. -- cgit 1.4.1-3-g733a5 From 8520535694e376b91d63c1243a9080b9f155aeff Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 6 Aug 2022 17:18:59 -0400 Subject: make NOP dyn casts not require anything about the vtable --- src/unsize.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/unsize.rs b/src/unsize.rs index 052ca0a082b..dd9d891ddbd 100644 --- a/src/unsize.rs +++ b/src/unsize.rs @@ -29,6 +29,7 @@ pub(crate) fn unsized_info<'tcx>( let old_info = old_info.expect("unsized_info: missing old info for trait upcasting coercion"); if data_a.principal_def_id() == data_b.principal_def_id() { + // A NOP cast that doesn't actually change anything, should be allowed even with invalid vtables. return old_info; } -- cgit 1.4.1-3-g733a5 From bacb4db48c7fe109a7d480b3b5b1cd03898db4a6 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 7 Aug 2022 12:27:38 +0200 Subject: Only encode position from start of file. --- compiler/rustc_metadata/src/rmeta/decoder.rs | 18 ++++++++---------- compiler/rustc_metadata/src/rmeta/encoder.rs | 26 +++++++++++++------------- compiler/rustc_span/src/lib.rs | 4 ---- compiler/rustc_span/src/source_map.rs | 4 +--- 4 files changed, 22 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index a58f6e6e1de..4b2dcc7a70b 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -581,28 +581,26 @@ impl<'a, 'tcx> Decodable> for Span { foreign_data.imported_source_file(metadata_index, sess) }; - // Make sure our binary search above is correct. + // Make sure our span is well-formed. debug_assert!( - lo >= source_file.original_start_pos && lo <= source_file.original_end_pos, - "Bad binary search: lo={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}", + lo + source_file.original_start_pos <= source_file.original_end_pos, + "Malformed encoded span: lo={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}", lo, source_file.original_start_pos, source_file.original_end_pos ); - // Make sure we correctly filtered out invalid spans during encoding + // Make sure we correctly filtered out invalid spans during encoding. debug_assert!( - hi >= source_file.original_start_pos && hi <= source_file.original_end_pos, - "Bad binary search: hi={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}", + hi + source_file.original_start_pos <= source_file.original_end_pos, + "Malformed encoded span: hi={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}", hi, source_file.original_start_pos, source_file.original_end_pos ); - let lo = - (lo + source_file.translated_source_file.start_pos) - source_file.original_start_pos; - let hi = - (hi + source_file.translated_source_file.start_pos) - source_file.original_start_pos; + let lo = lo + source_file.translated_source_file.start_pos; + let hi = hi + source_file.translated_source_file.start_pos; // Do not try to decode parent for foreign spans. Span::new(lo, hi, ctxt, None) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 463cfece715..6b3118e7152 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -235,6 +235,7 @@ impl<'a, 'tcx> Encodable> for Span { (source_map.files()[source_file_index].clone(), source_file_index); } let (ref source_file, source_file_index) = s.source_file_cache; + debug_assert!(source_file.contains(span.lo)); if !source_file.contains(span.hi) { // Unfortunately, macro expansion still sometimes generates Spans @@ -242,9 +243,6 @@ impl<'a, 'tcx> Encodable> for Span { return TAG_PARTIAL_SPAN.encode(s); } - // Length is independent of the span provenance. - let len = span.hi - span.lo; - // There are two possible cases here: // 1. This span comes from a 'foreign' crate - e.g. some crate upstream of the // crate we are writing metadata for. When the metadata for *this* crate gets @@ -261,7 +259,7 @@ impl<'a, 'tcx> Encodable> for Span { // if we're a proc-macro crate. // This allows us to avoid loading the dependencies of proc-macro crates: all of // the information we need to decode `Span`s is stored in the proc-macro crate. - let (tag, lo, metadata_index) = if source_file.is_imported() && !s.is_proc_macro { + let (tag, metadata_index) = if source_file.is_imported() && !s.is_proc_macro { // To simplify deserialization, we 'rebase' this span onto the crate it originally came from // (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values // are relative to the source map information for the 'foreign' crate whose CrateNum @@ -271,18 +269,15 @@ impl<'a, 'tcx> Encodable> for Span { // // All of this logic ensures that the final result of deserialization is a 'normal' // Span that can be used without any additional trouble. - let (external_start_pos, metadata_index) = { + let metadata_index = { // Introduce a new scope so that we drop the 'lock()' temporary match &*source_file.external_src.lock() { - ExternalSource::Foreign { original_start_pos, metadata_index, .. } => { - (*original_start_pos, *metadata_index) - } + ExternalSource::Foreign { metadata_index, .. } => *metadata_index, src => panic!("Unexpected external source {:?}", src), } }; - let lo = (span.lo - source_file.start_pos) + external_start_pos; - (TAG_VALID_SPAN_FOREIGN, lo, metadata_index) + (TAG_VALID_SPAN_FOREIGN, metadata_index) } else { // Record the fact that we need to encode the data for this `SourceFile` let source_files = @@ -291,14 +286,19 @@ impl<'a, 'tcx> Encodable> for Span { let metadata_index: u32 = metadata_index.try_into().expect("cannot export more than U32_MAX files"); - (TAG_VALID_SPAN_LOCAL, span.lo, metadata_index) + (TAG_VALID_SPAN_LOCAL, metadata_index) }; - tag.encode(s); - lo.encode(s); + // Encode the start position relative to the file start, so we profit more from the + // variable-length integer encoding. + let lo = span.lo - source_file.start_pos; // Encode length which is usually less than span.hi and profits more // from the variable-length integer encoding that we use. + let len = span.hi - span.lo; + + tag.encode(s); + lo.encode(s); len.encode(s); // Encode the index of the `SourceFile` for the span, in order to make decoding faster. diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index bae05f2f02e..8d26cd6bee3 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1094,10 +1094,6 @@ pub enum ExternalSource { Unneeded, Foreign { kind: ExternalSourceKind, - /// This SourceFile's byte-offset within the source_map of its original crate. - original_start_pos: BytePos, - /// The end of this SourceFile within the source_map of its original crate. - original_end_pos: BytePos, /// Index of the file inside metadata. metadata_index: u32, }, diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 387777f7af6..c0fbb7f2c9f 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -336,7 +336,7 @@ impl SourceMap { mut file_local_non_narrow_chars: Vec, mut file_local_normalized_pos: Vec, original_start_pos: BytePos, - original_end_pos: BytePos, + _original_end_pos: BytePos, metadata_index: u32, ) -> Lrc { let start_pos = self @@ -382,8 +382,6 @@ impl SourceMap { src_hash, external_src: Lock::new(ExternalSource::Foreign { kind: ExternalSourceKind::AbsentOk, - original_start_pos, - original_end_pos, metadata_index, }), start_pos, -- cgit 1.4.1-3-g733a5 From 1883d1f14146959cfa9cdf1ed43e5d1ad013e07e Mon Sep 17 00:00:00 2001 From: Kartavya Vashishtha Date: Sun, 7 Aug 2022 20:39:11 +0530 Subject: activate assoc item test --- crates/ide-diagnostics/src/handlers/inactive_code.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ide-diagnostics/src/handlers/inactive_code.rs b/crates/ide-diagnostics/src/handlers/inactive_code.rs index 97ea5c456a6..6715823f1ff 100644 --- a/crates/ide-diagnostics/src/handlers/inactive_code.rs +++ b/crates/ide-diagnostics/src/handlers/inactive_code.rs @@ -112,12 +112,12 @@ fn f() { struct Foo; impl Foo { #[cfg(any())] pub fn f() {} - //*************************** weak: code is inactive due to #[cfg] directives + //^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives } trait Bar { #[cfg(any())] pub fn f() {} - //*************************** weak: code is inactive due to #[cfg] directives + //^^^^^^^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives } "#, ); -- cgit 1.4.1-3-g733a5 From 196f389a708d5e0002a1d3b4e1059d43dc4542fb Mon Sep 17 00:00:00 2001 From: Kartavya Vashishtha Date: Mon, 8 Aug 2022 16:40:29 +0530 Subject: try adding diagnostrics for AssocItems --- crates/hir-def/src/data.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs index 35c8708955a..1b4f4ed04ac 100644 --- a/crates/hir-def/src/data.rs +++ b/crates/hir-def/src/data.rs @@ -2,7 +2,7 @@ use std::sync::Arc; -use hir_expand::{name::Name, AstId, ExpandResult, HirFileId, MacroCallId, MacroDefKind}; +use hir_expand::{name::Name, AstId, ExpandResult, HirFileId, MacroCallId, MacroDefKind, InFile}; use smallvec::SmallVec; use syntax::ast; @@ -12,7 +12,7 @@ use crate::{ db::DefDatabase, intern::Interned, item_tree::{self, AssocItem, FnFlags, ItemTree, ItemTreeId, ModItem, Param, TreeId}, - nameres::{attr_resolution::ResolvedAttr, proc_macro::ProcMacroKind, DefMap}, + nameres::{attr_resolution::ResolvedAttr, proc_macro::ProcMacroKind, DefMap, diagnostics::DefDiagnostic}, type_ref::{TraitRef, TypeBound, TypeRef}, visibility::RawVisibility, AssocItemId, AstIdWithPath, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, @@ -479,6 +479,13 @@ impl<'a> AssocItemCollector<'a> { 'items: for &item in assoc_items { let attrs = item_tree.attrs(self.db, self.module_id.krate, ModItem::from(item).into()); if !attrs.is_cfg_enabled(self.expander.cfg_options()) { + self.def_map.push_diagnostic(DefDiagnostic::unconfigured_code( + self.module_id.local_id, + InFile::new(tree_id.file_id(), item.ast_id(&item_tree).upcast()), + attrs.cfg().unwrap(), + self.expander.cfg_options().clone() + )); + dbg!("Ignoring assoc item!"); continue; } -- cgit 1.4.1-3-g733a5 From c1eae3d0281e1e34f64332b02a7dc4bdd0ae6e5b Mon Sep 17 00:00:00 2001 From: Kartavya Vashishtha Date: Mon, 8 Aug 2022 16:45:27 +0530 Subject: make diagnostic function public --- crates/hir-def/src/nameres.rs | 8 ++++++++ crates/hir-def/src/nameres/diagnostics.rs | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index 45f631936d2..a2181a6bf41 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -511,6 +511,14 @@ impl DefMap { self.diagnostics.as_slice() } + pub fn push_diagnostic(&mut self, d: DefDiagnostic) { + self.diagnostics.push(d) + } + + pub fn push_diagnostics(&mut self, i: impl Iterator) { + self.diagnostics.extend(i) + } + pub fn recursion_limit(&self) -> Option { self.recursion_limit } diff --git a/crates/hir-def/src/nameres/diagnostics.rs b/crates/hir-def/src/nameres/diagnostics.rs index 0d01f6d0aba..ed7e920fd2b 100644 --- a/crates/hir-def/src/nameres/diagnostics.rs +++ b/crates/hir-def/src/nameres/diagnostics.rs @@ -73,7 +73,7 @@ impl DefDiagnostic { Self { in_module: container, kind: DefDiagnosticKind::UnresolvedImport { id, index } } } - pub(super) fn unconfigured_code( + pub fn unconfigured_code( container: LocalModuleId, ast: AstId, cfg: CfgExpr, -- cgit 1.4.1-3-g733a5 From 1cde1a31a17feb9cd61c65176694f26886ca5e22 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 8 Aug 2022 09:04:26 -0400 Subject: also update anyhow in codegen_cranelift --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 532049c858d..402fbb16f97 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,9 +15,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.56" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" +checksum = "c794e162a5eff65c72ef524dfe393eb923c354e350bb78b9c7383df13f3bc142" [[package]] name = "ar" -- cgit 1.4.1-3-g733a5 From 526553e4a35926f0a06dbdd48fec904db6483b03 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 8 Aug 2022 18:30:01 +0200 Subject: Rustup to rustc 1.65.0-nightly (d394408fb 2022-08-07) --- build_sysroot/Cargo.lock | 12 ++++++------ rust-toolchain | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build_sysroot/Cargo.lock b/build_sysroot/Cargo.lock index 7b2cdd27336..e9bd9167acd 100644 --- a/build_sysroot/Cargo.lock +++ b/build_sysroot/Cargo.lock @@ -56,9 +56,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.75" +version = "0.1.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e3183e88f659a862835db8f4b67dbeed3d93e44dd4927eef78edb1c149d784" +checksum = "413b6b13f725a46cdec40364e0c1d564a22cf0aaac5f1e267a129d956478a6b4" dependencies = [ "rustc-std-workspace-core", ] @@ -123,9 +123,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7668753748e445859e4e373c3d41117235d9feed578392f5a3a73efdc751ca4a" +checksum = "897cd85af6387be149f55acf168e41be176a02de7872403aaab184afc2f327e6" dependencies = [ "compiler_builtins", "libc", @@ -135,9 +135,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b" dependencies = [ "rustc-std-workspace-core", ] diff --git a/rust-toolchain b/rust-toolchain index ca1813a6ed0..9b9ed85f6c7 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2022-07-27" +channel = "nightly-2022-08-08" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] -- cgit 1.4.1-3-g733a5 From 0d41f9145ce4f884a53fddefe0624060eb22609b Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 8 Aug 2022 21:12:04 +0200 Subject: Remove unused parameter. --- compiler/rustc_metadata/src/rmeta/decoder.rs | 1 - compiler/rustc_span/src/source_map.rs | 1 - compiler/rustc_span/src/source_map/tests.rs | 1 - 3 files changed, 3 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 4b2dcc7a70b..2a3693a360f 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1581,7 +1581,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { non_narrow_chars, normalized_pos, start_pos, - end_pos, source_file_index, ); debug!( diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index c0fbb7f2c9f..108b169e306 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -336,7 +336,6 @@ impl SourceMap { mut file_local_non_narrow_chars: Vec, mut file_local_normalized_pos: Vec, original_start_pos: BytePos, - _original_end_pos: BytePos, metadata_index: u32, ) -> Lrc { let start_pos = self diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs index 2cada019b7f..3058ec45a64 100644 --- a/compiler/rustc_span/src/source_map/tests.rs +++ b/compiler/rustc_span/src/source_map/tests.rs @@ -251,7 +251,6 @@ fn t10() { non_narrow_chars, normalized_pos, start_pos, - end_pos, 0, ); -- cgit 1.4.1-3-g733a5 From 08c97323dee8b8558c8e1dc770885f0095360d32 Mon Sep 17 00:00:00 2001 From: BlackHoleFox Date: Mon, 8 Aug 2022 17:49:19 -0700 Subject: Add standard C error function aliases Aids the discoverability of `io::Error::last_os_error()` by linking to commonly used error number functions from C/C++. --- library/std/src/io/error.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index ff7fdcae16f..4e541dda906 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -564,6 +564,8 @@ impl Error { /// println!("last OS error: {os_error:?}"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[doc(alias = "GetLastError")] + #[doc(alias = "errno")] #[must_use] #[inline] pub fn last_os_error() -> Error { -- cgit 1.4.1-3-g733a5 From 5810c8188a2cfc36a8026ae068c985aa9a2f5f2b Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Mon, 8 Aug 2022 20:20:45 -0400 Subject: Implement IntoFuture type inference --- crates/hir-expand/src/mod_path.rs | 1 + crates/hir-expand/src/name.rs | 2 ++ crates/hir-ty/src/infer.rs | 5 ++- crates/hir-ty/src/tests/traits.rs | 25 ++++++++++++++ crates/hir/src/lib.rs | 2 ++ crates/hir/src/source_analyzer.rs | 2 ++ crates/ide-assists/src/utils/suggest_name.rs | 1 + crates/ide-completion/src/completions/keyword.rs | 44 +++++++++++++----------- crates/test-utils/src/minicore.rs | 15 ++++++++ 9 files changed, 75 insertions(+), 22 deletions(-) diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs index fea09521e87..9ddafe01810 100644 --- a/crates/hir-expand/src/mod_path.rs +++ b/crates/hir-expand/src/mod_path.rs @@ -257,6 +257,7 @@ macro_rules! __known_path { (core::ops::RangeToInclusive) => {}; (core::ops::RangeInclusive) => {}; (core::future::Future) => {}; + (core::future::IntoFuture) => {}; (core::ops::Try) => {}; ($path:path) => { compile_error!("Please register your known path in the path module") diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs index 47d191822d8..757db79db4d 100644 --- a/crates/hir-expand/src/name.rs +++ b/crates/hir-expand/src/name.rs @@ -258,6 +258,7 @@ pub mod known { Try, Ok, Future, + IntoFuture, Result, Option, Output, @@ -391,6 +392,7 @@ pub mod known { future_trait, index, index_mut, + into_future, mul_assign, mul, neg, diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 46eeea0e6fc..95a7229e879 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -875,7 +875,10 @@ impl<'a> InferenceContext<'a> { } fn resolve_future_future_output(&self) -> Option { - let trait_ = self.resolve_lang_item(name![future_trait])?.as_trait()?; + let trait_ = self + .resolver + .resolve_known_trait(self.db.upcast(), &path![core::future::IntoFuture]) + .or_else(|| self.resolve_lang_item(name![future_trait])?.as_trait())?; self.db.trait_data(trait_).associated_type_by_name(&name![Output]) } diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs index 75802a5eb4d..730ebe2357d 100644 --- a/crates/hir-ty/src/tests/traits.rs +++ b/crates/hir-ty/src/tests/traits.rs @@ -137,6 +137,31 @@ fn not_send() -> Box + 'static> { ); } +#[test] +fn into_future_trait() { + check_types( + r#" +//- minicore: future +struct Futurable; +impl core::future::IntoFuture for Futurable { + type Output = u64; + type IntoFuture = IntFuture; +} + +struct IntFuture; +impl core::future::Future for IntFuture { + type Output = u64; +} + +fn test() { + let r = Futurable; + let v = r.await; + v; +} //^ u64 +"#, + ); +} + #[test] fn infer_try() { check_types( diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 8f984210e11..800ea58ba29 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -2780,6 +2780,8 @@ impl Type { /// Checks that particular type `ty` implements `std::future::Future`. /// This function is used in `.await` syntax completion. pub fn impls_future(&self, db: &dyn HirDatabase) -> bool { + // FIXME: This should be checking for IntoFuture trait, but I don't know how to find the + // right TraitId in this crate. let std_future_trait = db .lang_item(self.env.krate, SmolStr::new_inline("future_trait")) .and_then(|it| it.as_trait()); diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index f5e2e443070..756772cf84e 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -269,6 +269,8 @@ impl SourceAnalyzer { db: &dyn HirDatabase, await_expr: &ast::AwaitExpr, ) -> Option { + // FIXME This should be pointing to the poll of IntoFuture::Output's Future impl, but I + // don't know how to resolve the Output type so that we can query for its poll method. let ty = self.ty_of_expr(db, &await_expr.expr()?.into())?; let op_fn = db diff --git a/crates/ide-assists/src/utils/suggest_name.rs b/crates/ide-assists/src/utils/suggest_name.rs index 779cdbc93c5..68d59daef48 100644 --- a/crates/ide-assists/src/utils/suggest_name.rs +++ b/crates/ide-assists/src/utils/suggest_name.rs @@ -55,6 +55,7 @@ const USELESS_METHODS: &[&str] = &[ "iter", "into_iter", "iter_mut", + "into_future", ]; pub(crate) fn for_generic_parameter(ty: &ast::ImplTraitType) -> SmolStr { diff --git a/crates/ide-completion/src/completions/keyword.rs b/crates/ide-completion/src/completions/keyword.rs index 3989a451bde..032b23725f8 100644 --- a/crates/ide-completion/src/completions/keyword.rs +++ b/crates/ide-completion/src/completions/keyword.rs @@ -75,16 +75,17 @@ impl Future for A {} fn foo(a: A) { a.$0 } "#, expect![[r#" - kw await expr.await - sn box Box::new(expr) - sn call function(expr) - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr + kw await expr.await + me into_future() (as IntoFuture) fn(self) -> ::IntoFuture + sn box Box::new(expr) + sn call function(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr "#]], ); @@ -98,18 +99,19 @@ fn foo() { } "#, expect![[r#" - kw await expr.await - sn box Box::new(expr) - sn call function(expr) - sn dbg dbg!(expr) - sn dbgr dbg!(&expr) - sn let let - sn letm let mut - sn match match expr {} - sn ref &expr - sn refm &mut expr + kw await expr.await + me into_future() (use core::future::IntoFuture) fn(self) -> ::IntoFuture + sn box Box::new(expr) + sn call function(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr "#]], - ) + ); } #[test] diff --git a/crates/test-utils/src/minicore.rs b/crates/test-utils/src/minicore.rs index f48d1ec66aa..6df29db4745 100644 --- a/crates/test-utils/src/minicore.rs +++ b/crates/test-utils/src/minicore.rs @@ -471,6 +471,21 @@ pub mod future { #[lang = "poll"] fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll; } + + pub trait IntoFuture { + type Output; + type IntoFuture: Future; + #[lang = "into_future"] + fn into_future(self) -> Self::IntoFuture; + } + + impl IntoFuture for F { + type Output = F::Output; + type IntoFuture = F; + fn into_future(self) -> F { + self + } + } } pub mod task { pub enum Poll { -- cgit 1.4.1-3-g733a5 From f4bf8cd100deb76bd424897c9796f0886468c77a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 9 Aug 2022 07:04:37 +0000 Subject: Extend comma suggestion to cases where fields arent missing --- compiler/rustc_typeck/src/check/expr.rs | 55 ++++++++++++++-------- src/test/ui/structs/struct-record-suggestion.fixed | 24 ++++++++-- src/test/ui/structs/struct-record-suggestion.rs | 24 ++++++++-- .../ui/structs/struct-record-suggestion.stderr | 23 +++++++-- 4 files changed, 96 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 6e97b0bf2ab..a0fa27a1018 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1518,7 +1518,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut error_happened = false; // Type-check each field. - for field in ast_fields { + for (idx, field) in ast_fields.iter().enumerate() { let ident = tcx.adjust_ident(field.ident, variant.def_id); let field_type = if let Some((i, v_field)) = remaining_fields.remove(&ident) { seen_fields.insert(ident, field.span); @@ -1556,7 +1556,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Make sure to give a type to the field even if there's // an error, so we can continue type-checking. - self.check_expr_coercable_to_type(&field.expr, field_type, None); + let ty = self.check_expr_with_hint(&field.expr, field_type); + let (_, diag) = + self.demand_coerce_diag(&field.expr, ty, field_type, None, AllowTwoPhase::No); + + if let Some(mut diag) = diag { + if idx == ast_fields.len() - 1 && remaining_fields.is_empty() { + self.suggest_fru_from_range(field, variant, substs, &mut diag); + } + diag.emit(); + } } // Make sure the programmer specified correct number of fields. @@ -1784,25 +1793,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); err.span_label(span, format!("missing {remaining_fields_names}{truncated_fields_error}")); - // If the last field is a range literal, but it isn't supposed to be, then they probably - // meant to use functional update syntax. - // + if let Some(last) = ast_fields.last() { + self.suggest_fru_from_range(last, variant, substs, &mut err); + } + + err.emit(); + } + + /// If the last field is a range literal, but it isn't supposed to be, then they probably + /// meant to use functional update syntax. + fn suggest_fru_from_range( + &self, + last_expr_field: &hir::ExprField<'tcx>, + variant: &ty::VariantDef, + substs: SubstsRef<'tcx>, + err: &mut Diagnostic, + ) { // I don't use 'is_range_literal' because only double-sided, half-open ranges count. - if let Some(( - last, - ExprKind::Struct( + if let ExprKind::Struct( QPath::LangItem(LangItem::Range, ..), &[ref range_start, ref range_end], _, - ), - )) = ast_fields.last().map(|last| (last, &last.expr.kind)) && - let variant_field = - variant.fields.iter().find(|field| field.ident(self.tcx) == last.ident) && - let range_def_id = self.tcx.lang_items().range_struct() && - variant_field - .and_then(|field| field.ty(self.tcx, substs).ty_adt_def()) - .map(|adt| adt.did()) - != range_def_id + ) = last_expr_field.expr.kind + && let variant_field = + variant.fields.iter().find(|field| field.ident(self.tcx) == last_expr_field.ident) + && let range_def_id = self.tcx.lang_items().range_struct() + && variant_field + .and_then(|field| field.ty(self.tcx, substs).ty_adt_def()) + .map(|adt| adt.did()) + != range_def_id { let instead = self .tcx @@ -1818,8 +1837,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MaybeIncorrect, ); } - - err.emit(); } /// Report an error for a struct field expression when there are invisible fields. diff --git a/src/test/ui/structs/struct-record-suggestion.fixed b/src/test/ui/structs/struct-record-suggestion.fixed index 48144cd1ce2..49e38b196de 100644 --- a/src/test/ui/structs/struct-record-suggestion.fixed +++ b/src/test/ui/structs/struct-record-suggestion.fixed @@ -6,11 +6,29 @@ struct A { d: usize, } -fn main() { - let q = A { c: 5, .. Default::default() }; +fn a() { + let q = A { c: 5,..Default::default() }; //~^ ERROR mismatched types //~| ERROR missing fields //~| HELP separate the last named field with a comma - let r = A { c: 5, .. Default::default() }; + let r = A { c: 5, ..Default::default() }; assert_eq!(q, r); } + +#[derive(Debug, Default, Eq, PartialEq)] +struct B { + b: u32, +} + +fn b() { + let q = B { b: 1,..Default::default() }; + //~^ ERROR mismatched types + //~| HELP separate the last named field with a comma + let r = B { b: 1 }; + assert_eq!(q, r); +} + +fn main() { + a(); + b(); +} diff --git a/src/test/ui/structs/struct-record-suggestion.rs b/src/test/ui/structs/struct-record-suggestion.rs index 6d169d5c6db..901f310c8bd 100644 --- a/src/test/ui/structs/struct-record-suggestion.rs +++ b/src/test/ui/structs/struct-record-suggestion.rs @@ -6,11 +6,29 @@ struct A { d: usize, } -fn main() { - let q = A { c: 5 .. Default::default() }; +fn a() { + let q = A { c: 5..Default::default() }; //~^ ERROR mismatched types //~| ERROR missing fields //~| HELP separate the last named field with a comma - let r = A { c: 5, .. Default::default() }; + let r = A { c: 5, ..Default::default() }; assert_eq!(q, r); } + +#[derive(Debug, Default, Eq, PartialEq)] +struct B { + b: u32, +} + +fn b() { + let q = B { b: 1..Default::default() }; + //~^ ERROR mismatched types + //~| HELP separate the last named field with a comma + let r = B { b: 1 }; + assert_eq!(q, r); +} + +fn main() { + a(); + b(); +} diff --git a/src/test/ui/structs/struct-record-suggestion.stderr b/src/test/ui/structs/struct-record-suggestion.stderr index e5bd03117b9..66e9f021ed6 100644 --- a/src/test/ui/structs/struct-record-suggestion.stderr +++ b/src/test/ui/structs/struct-record-suggestion.stderr @@ -1,8 +1,8 @@ error[E0308]: mismatched types --> $DIR/struct-record-suggestion.rs:10:20 | -LL | let q = A { c: 5 .. Default::default() }; - | ^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found struct `std::ops::Range` +LL | let q = A { c: 5..Default::default() }; + | ^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found struct `std::ops::Range` | = note: expected type `u64` found struct `std::ops::Range<{integer}>` @@ -10,15 +10,28 @@ LL | let q = A { c: 5 .. Default::default() }; error[E0063]: missing fields `b` and `d` in initializer of `A` --> $DIR/struct-record-suggestion.rs:10:13 | -LL | let q = A { c: 5 .. Default::default() }; +LL | let q = A { c: 5..Default::default() }; | ^ missing `b` and `d` | help: to set the remaining fields from `Default::default()`, separate the last named field with a comma | -LL | let q = A { c: 5, .. Default::default() }; +LL | let q = A { c: 5,..Default::default() }; | + -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/struct-record-suggestion.rs:24:20 + | +LL | let q = B { b: 1..Default::default() }; + | ^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found struct `std::ops::Range` + | + = note: expected type `u32` + found struct `std::ops::Range<{integer}>` +help: to set the remaining fields from `Default::default()`, separate the last named field with a comma + | +LL | let q = B { b: 1,..Default::default() }; + | + + +error: aborting due to 3 previous errors Some errors have detailed explanations: E0063, E0308. For more information about an error, try `rustc --explain E0063`. -- cgit 1.4.1-3-g733a5 From fa6480e43d3b9195fdc2077e32a3ee653409ee89 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 9 Aug 2022 12:27:34 +0000 Subject: Remove most trap functions and remove all trapnz usages --- src/base.rs | 18 ++++-------------- src/discriminant.rs | 20 +++++++++++--------- src/inline_asm.rs | 18 ++++++++++++++++-- src/intrinsics/cpuid.rs | 2 +- src/intrinsics/llvm.rs | 1 + src/intrinsics/mod.rs | 6 +----- src/intrinsics/simd.rs | 15 ++++++++++----- src/trap.rs | 25 +------------------------ 8 files changed, 45 insertions(+), 60 deletions(-) diff --git a/src/base.rs b/src/base.rs index 122e103ff62..2c04cf47268 100644 --- a/src/base.rs +++ b/src/base.rs @@ -90,7 +90,8 @@ pub(crate) fn codegen_fn<'tcx>( if !crate::constant::check_constants(&mut fx) { fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]); fx.bcx.switch_to_block(fx.block_map[START_BLOCK]); - crate::trap::trap_unreachable(&mut fx, "compilation should have been aborted"); + // compilation should have been aborted + fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); } else if arg_uninhabited { fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]); fx.bcx.switch_to_block(fx.block_map[START_BLOCK]); @@ -457,17 +458,8 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) { template, operands, *options, + *destination, ); - - match *destination { - Some(destination) => { - let destination_block = fx.get_block(destination); - fx.bcx.ins().jump(destination_block, &[]); - } - None => { - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); - } - } } TerminatorKind::Resume | TerminatorKind::Abort => { // FIXME implement unwinding @@ -711,9 +703,7 @@ fn codegen_stmt<'tcx>( Rvalue::Discriminant(place) => { let place = codegen_place(fx, place); let value = place.to_cvalue(fx); - let discr = - crate::discriminant::codegen_get_discriminant(fx, value, dest_layout); - lval.write_cvalue(fx, discr); + crate::discriminant::codegen_get_discriminant(fx, lval, value, dest_layout); } Rvalue::Repeat(ref operand, times) => { let operand = codegen_operand(fx, operand); diff --git a/src/discriminant.rs b/src/discriminant.rs index f619bb5ed5e..e41ae1fbdba 100644 --- a/src/discriminant.rs +++ b/src/discriminant.rs @@ -62,16 +62,14 @@ pub(crate) fn codegen_set_discriminant<'tcx>( pub(crate) fn codegen_get_discriminant<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, + dest: CPlace<'tcx>, value: CValue<'tcx>, dest_layout: TyAndLayout<'tcx>, -) -> CValue<'tcx> { +) { let layout = value.layout(); - if layout.abi == Abi::Uninhabited { - let true_ = fx.bcx.ins().iconst(types::I32, 1); - fx.bcx.ins().trapnz(true_, TrapCode::UnreachableCodeReached); - // Return a dummy value - return CValue::by_ref(Pointer::const_addr(fx, 0), dest_layout); + if layout.abi.is_uninhabited() { + return; } let (tag_scalar, tag_field, tag_encoding) = match &layout.variants { @@ -89,7 +87,9 @@ pub(crate) fn codegen_get_discriminant<'tcx>( } else { ty::ScalarInt::try_from_uint(discr_val, dest_layout.size).unwrap() }; - return CValue::const_val(fx, dest_layout, discr_val); + let res = CValue::const_val(fx, dest_layout, discr_val); + dest.write_cvalue(fx, res); + return; } Variants::Multiple { tag, tag_field, tag_encoding, variants: _ } => { (tag, *tag_field, tag_encoding) @@ -110,7 +110,8 @@ pub(crate) fn codegen_get_discriminant<'tcx>( _ => false, }; let val = clif_intcast(fx, tag, cast_to, signed); - CValue::by_val(val, dest_layout) + let res = CValue::by_val(val, dest_layout); + dest.write_cvalue(fx, res); } TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start } => { // Rebase from niche values to discriminants, and check @@ -170,7 +171,8 @@ pub(crate) fn codegen_get_discriminant<'tcx>( let dataful_variant = fx.bcx.ins().iconst(cast_to, i64::from(dataful_variant.as_u32())); let discr = fx.bcx.ins().select(is_niche, niche_discr, dataful_variant); - CValue::by_val(discr, dest_layout) + let res = CValue::by_val(discr, dest_layout); + dest.write_cvalue(fx, res); } } } diff --git a/src/inline_asm.rs b/src/inline_asm.rs index 241de5e3653..7b1a39c675c 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -15,13 +15,13 @@ pub(crate) fn codegen_inline_asm<'tcx>( template: &[InlineAsmTemplatePiece], operands: &[InlineAsmOperand<'tcx>], options: InlineAsmOptions, + destination: Option, ) { // FIXME add .eh_frame unwind info directives if !template.is_empty() { if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) { - let true_ = fx.bcx.ins().iconst(types::I32, 1); - fx.bcx.ins().trapnz(true_, TrapCode::User(1)); + fx.bcx.ins().trap(TrapCode::User(1)); return; } else if template[0] == InlineAsmTemplatePiece::String("movq %rbx, ".to_string()) && matches!( @@ -101,12 +101,16 @@ pub(crate) fn codegen_inline_asm<'tcx>( ebx_place.write_cvalue(fx, CValue::by_val(ebx, fx.layout_of(fx.tcx.types.u32))); ecx_place.write_cvalue(fx, CValue::by_val(ecx, fx.layout_of(fx.tcx.types.u32))); edx_place.write_cvalue(fx, CValue::by_val(edx, fx.layout_of(fx.tcx.types.u32))); + let destination_block = fx.get_block(destination.unwrap()); + fx.bcx.ins().jump(destination_block, &[]); return; } else if fx.tcx.symbol_name(fx.instance).name.starts_with("___chkstk") { // ___chkstk, ___chkstk_ms and __alloca are only used on Windows crate::trap::trap_unimplemented(fx, "Stack probes are not supported"); + return; } else if fx.tcx.symbol_name(fx.instance).name == "__alloca" { crate::trap::trap_unimplemented(fx, "Alloca is not supported"); + return; } } @@ -175,6 +179,16 @@ pub(crate) fn codegen_inline_asm<'tcx>( } call_inline_asm(fx, &asm_name, asm_gen.stack_slot_size, inputs, outputs); + + match destination { + Some(destination) => { + let destination_block = fx.get_block(destination); + fx.bcx.ins().jump(destination_block, &[]); + } + None => { + fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + } + } } struct InlineAssemblyGenerator<'a, 'tcx> { diff --git a/src/intrinsics/cpuid.rs b/src/intrinsics/cpuid.rs index d02dfd93c3e..5120b89c4e8 100644 --- a/src/intrinsics/cpuid.rs +++ b/src/intrinsics/cpuid.rs @@ -62,7 +62,7 @@ pub(crate) fn codegen_cpuid_call<'tcx>( fx.bcx.ins().jump(dest, &[zero, zero, proc_info_ecx, proc_info_edx]); fx.bcx.switch_to_block(unsupported_leaf); - crate::trap::trap_unreachable( + crate::trap::trap_unimplemented( fx, "__cpuid_count arch intrinsic doesn't yet support specified leaf", ); diff --git a/src/intrinsics/llvm.rs b/src/intrinsics/llvm.rs index 869670c8cfa..a799dca938e 100644 --- a/src/intrinsics/llvm.rs +++ b/src/intrinsics/llvm.rs @@ -139,6 +139,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( .sess .warn(&format!("unsupported llvm intrinsic {}; replacing with trap", intrinsic)); crate::trap::trap_unimplemented(fx, intrinsic); + return; } } diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 77caf741acf..cb620822f2d 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -44,7 +44,7 @@ fn report_atomic_type_validation_error<'tcx>( ), ); // Prevent verifier error - crate::trap::trap_unreachable(fx, "compilation should not have succeeded"); + fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); } pub(crate) fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>) -> Option { @@ -849,8 +849,6 @@ fn codegen_regular_intrinsic_call<'tcx>( if fx.tcx.is_compiler_builtins(LOCAL_CRATE) { // special case for compiler-builtins to avoid having to patch it crate::trap::trap_unimplemented(fx, "128bit atomics not yet supported"); - let ret_block = fx.get_block(destination.unwrap()); - fx.bcx.ins().jump(ret_block, &[]); return; } else { fx.tcx @@ -882,8 +880,6 @@ fn codegen_regular_intrinsic_call<'tcx>( if fx.tcx.is_compiler_builtins(LOCAL_CRATE) { // special case for compiler-builtins to avoid having to patch it crate::trap::trap_unimplemented(fx, "128bit atomics not yet supported"); - let ret_block = fx.get_block(destination.unwrap()); - fx.bcx.ins().jump(ret_block, &[]); return; } else { fx.tcx diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index 30e3d112594..c7efdb392b7 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -14,7 +14,7 @@ fn report_simd_type_validation_error( ) { fx.tcx.sess.span_err(span, &format!("invalid monomorphization of `{}` intrinsic: expected SIMD input type, found non-SIMD `{}`", intrinsic, ty)); // Prevent verifier error - crate::trap::trap_unreachable(fx, "compilation should not have succeeded"); + fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); } pub(super) fn codegen_simd_intrinsic_call<'tcx>( @@ -157,7 +157,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( ), ); // Prevent verifier error - crate::trap::trap_unreachable(fx, "compilation should not have succeeded"); + fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); return; } } @@ -274,12 +274,17 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( idx_const } else { fx.tcx.sess.span_warn(span, "Index argument for `simd_extract` is not a constant"); - let res = crate::trap::trap_unimplemented_ret_value( + let trap_block = fx.bcx.create_block(); + let dummy_block = fx.bcx.create_block(); + let true_ = fx.bcx.ins().iconst(types::I8, 1); + fx.bcx.ins().brnz(true_, trap_block, &[]); + fx.bcx.ins().jump(dummy_block, &[]); + fx.bcx.switch_to_block(trap_block); + crate::trap::trap_unimplemented( fx, - ret.layout(), "Index argument for `simd_extract` is not a constant", ); - ret.write_cvalue(fx, res); + fx.bcx.switch_to_block(dummy_block); return; }; diff --git a/src/trap.rs b/src/trap.rs index 923269c4de9..82a2ec57954 100644 --- a/src/trap.rs +++ b/src/trap.rs @@ -25,33 +25,10 @@ fn codegen_print(fx: &mut FunctionCx<'_, '_, '_>, msg: &str) { fx.bcx.ins().call(puts, &[msg_ptr]); } -/// Use this for example when a function call should never return. This will fill the current block, -/// so you can **not** add instructions to it afterwards. -/// -/// Trap code: user65535 -pub(crate) fn trap_unreachable(fx: &mut FunctionCx<'_, '_, '_>, msg: impl AsRef) { - codegen_print(fx, msg.as_ref()); - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); -} /// Use this when something is unimplemented, but `libcore` or `libstd` requires it to codegen. -/// Unlike `trap_unreachable` this will not fill the current block, so you **must** add instructions -/// to it afterwards. /// /// Trap code: user65535 pub(crate) fn trap_unimplemented(fx: &mut FunctionCx<'_, '_, '_>, msg: impl AsRef) { codegen_print(fx, msg.as_ref()); - let true_ = fx.bcx.ins().iconst(types::I32, 1); - fx.bcx.ins().trapnz(true_, TrapCode::User(!0)); -} - -/// Like `trap_unimplemented` but returns a fake value of the specified type. -/// -/// Trap code: user65535 -pub(crate) fn trap_unimplemented_ret_value<'tcx>( - fx: &mut FunctionCx<'_, '_, 'tcx>, - dest_layout: TyAndLayout<'tcx>, - msg: impl AsRef, -) -> CValue<'tcx> { - trap_unimplemented(fx, msg); - CValue::by_ref(Pointer::const_addr(fx, 0), dest_layout) + fx.bcx.ins().trap(TrapCode::User(!0)); } -- cgit 1.4.1-3-g733a5 From 2bb7e1e6edf58c39faabb67cfab63dd8109d8055 Mon Sep 17 00:00:00 2001 From: YOSHIOKA Takuma Date: Wed, 10 Aug 2022 01:51:38 +0900 Subject: Guarantee `try_reserve` preserves the contents on error Update doc comments to make the guarantee explicit. However, some implementations does not have the statement though. * `HashMap`, `HashSet`: require guarantees on hashbrown side. * `PathBuf`: simply redirecting to `OsString`. Fixes #99606. --- library/alloc/src/collections/binary_heap.rs | 3 ++- library/alloc/src/collections/vec_deque/mod.rs | 3 ++- library/alloc/src/string.rs | 3 ++- library/alloc/src/vec/mod.rs | 3 ++- library/std/src/ffi/os_str.rs | 3 ++- library/std/src/sys_common/wtf8.rs | 3 ++- 6 files changed, 12 insertions(+), 6 deletions(-) diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs index 197e7aaaccf..4583bc9a158 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap.rs @@ -1010,7 +1010,8 @@ impl BinaryHeap { /// current length. The allocator may reserve more space to speculatively /// avoid frequent allocations. After calling `try_reserve`, capacity will be /// greater than or equal to `self.len() + additional` if it returns - /// `Ok(())`. Does nothing if capacity is already sufficient. + /// `Ok(())`. Does nothing if capacity is already sufficient. This method + /// preserves the contents even if an error occurs. /// /// # Errors /// diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 4d895d83745..41b6b6e4f52 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -794,7 +794,8 @@ impl VecDeque { /// in the given deque. The collection may reserve more space to speculatively avoid /// frequent reallocations. After calling `try_reserve`, capacity will be /// greater than or equal to `self.len() + additional` if it returns - /// `Ok(())`. Does nothing if capacity is already sufficient. + /// `Ok(())`. Does nothing if capacity is already sufficient. This method + /// preserves the contents even if an error occurs. /// /// # Errors /// diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index a5118e5333b..dce0beb4fe7 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -1080,7 +1080,8 @@ impl String { /// current length. The allocator may reserve more space to speculatively /// avoid frequent allocations. After calling `try_reserve`, capacity will be /// greater than or equal to `self.len() + additional` if it returns - /// `Ok(())`. Does nothing if capacity is already sufficient. + /// `Ok(())`. Does nothing if capacity is already sufficient. This method + /// preserves the contents even if an error occurs. /// /// # Errors /// diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index fa9f2131c0c..27027fa3a6f 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -875,7 +875,8 @@ impl Vec { /// in the given `Vec`. The collection may reserve more space to speculatively avoid /// frequent reallocations. After calling `try_reserve`, capacity will be /// greater than or equal to `self.len() + additional` if it returns - /// `Ok(())`. Does nothing if capacity is already sufficient. + /// `Ok(())`. Does nothing if capacity is already sufficient. This method + /// preserves the contents even if an error occurs. /// /// # Errors /// diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index a0a5c003d28..80ed34157e6 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -290,7 +290,8 @@ impl OsString { /// in the given `OsString`. The string may reserve more space to speculatively avoid /// frequent reallocations. After calling `try_reserve`, capacity will be /// greater than or equal to `self.len() + additional` if it returns `Ok(())`. - /// Does nothing if capacity is already sufficient. + /// Does nothing if capacity is already sufficient. This method preserves + /// the contents even if an error occurs. /// /// See the main `OsString` documentation information about encoding and capacity units. /// diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs index 57fa4989358..33e20756163 100644 --- a/library/std/src/sys_common/wtf8.rs +++ b/library/std/src/sys_common/wtf8.rs @@ -236,7 +236,8 @@ impl Wtf8Buf { /// in the given `Wtf8Buf`. The `Wtf8Buf` may reserve more space to avoid /// frequent reallocations. After calling `try_reserve`, capacity will be /// greater than or equal to `self.len() + additional`. Does nothing if - /// capacity is already sufficient. + /// capacity is already sufficient. This method preserves the contents even + /// if an error occurs. /// /// # Errors /// -- cgit 1.4.1-3-g733a5 From dc3219bb11f032e2e6f1d16deab2b5eabe9463d7 Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Tue, 9 Aug 2022 16:25:25 -0400 Subject: Suggest `.await` when type impls IntoFuture --- crates/hir/src/lib.rs | 23 ++++++++++++++------- crates/ide-completion/src/completions/keyword.rs | 26 ++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 800ea58ba29..7f16634afe1 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -2780,19 +2780,28 @@ impl Type { /// Checks that particular type `ty` implements `std::future::Future`. /// This function is used in `.await` syntax completion. pub fn impls_future(&self, db: &dyn HirDatabase) -> bool { - // FIXME: This should be checking for IntoFuture trait, but I don't know how to find the - // right TraitId in this crate. - let std_future_trait = db - .lang_item(self.env.krate, SmolStr::new_inline("future_trait")) - .and_then(|it| it.as_trait()); - let std_future_trait = match std_future_trait { + let trait_ = db + .lang_item(self.env.krate, SmolStr::new_inline("into_future")) + .and_then(|it| { + let into_future_fn = it.as_function()?; + let assoc_item = as_assoc_item(db, AssocItem::Function, into_future_fn)?; + let into_future_trait = assoc_item.containing_trait_or_trait_impl(db)?; + Some(into_future_trait.id) + }) + .or_else(|| { + let future_trait = + db.lang_item(self.env.krate, SmolStr::new_inline("future_trait"))?; + future_trait.as_trait() + }); + + let trait_ = match trait_ { Some(it) => it, None => return false, }; let canonical_ty = Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) }; - method_resolution::implements_trait(&canonical_ty, db, self.env.clone(), std_future_trait) + method_resolution::implements_trait(&canonical_ty, db, self.env.clone(), trait_) } /// Checks that particular type `ty` implements `std::ops::FnOnce`. diff --git a/crates/ide-completion/src/completions/keyword.rs b/crates/ide-completion/src/completions/keyword.rs index 032b23725f8..1d03c8cc5ca 100644 --- a/crates/ide-completion/src/completions/keyword.rs +++ b/crates/ide-completion/src/completions/keyword.rs @@ -114,6 +114,32 @@ fn foo() { ); } + #[test] + fn test_completion_await_impls_into_future() { + check( + r#" +//- minicore: future +use core::future::*; +struct A {} +impl IntoFuture for A {} +fn foo(a: A) { a.$0 } +"#, + expect![[r#" + kw await expr.await + me into_future() (as IntoFuture) fn(self) -> ::IntoFuture + sn box Box::new(expr) + sn call function(expr) + sn dbg dbg!(expr) + sn dbgr dbg!(&expr) + sn let let + sn letm let mut + sn match match expr {} + sn ref &expr + sn refm &mut expr + "#]], + ); + } + #[test] fn let_semi() { cov_mark::check!(let_semi); -- cgit 1.4.1-3-g733a5 From e087871915a46943db670b3e16bd12f25a1d11a2 Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Tue, 9 Aug 2022 20:23:40 -0400 Subject: Make the GATS self outlives error take into GATs in the inputs --- compiler/rustc_typeck/src/check/wfcheck.rs | 2 +- src/test/ui/generic-associated-types/self-outlives-lint.rs | 13 +++++++++++++ .../ui/generic-associated-types/self-outlives-lint.stderr | 13 ++++++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index d0334cd0df7..dbbae3e8a64 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -383,7 +383,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe tcx, param_env, item_hir_id, - sig.output(), + sig.inputs_and_output, // We also assume that all of the function signature's parameter types // are well formed. &sig.inputs().iter().copied().collect(), diff --git a/src/test/ui/generic-associated-types/self-outlives-lint.rs b/src/test/ui/generic-associated-types/self-outlives-lint.rs index 300907adbfc..9bb42d4ff1c 100644 --- a/src/test/ui/generic-associated-types/self-outlives-lint.rs +++ b/src/test/ui/generic-associated-types/self-outlives-lint.rs @@ -210,4 +210,17 @@ trait StaticReturnAndTakes<'a> { fn bar<'b>(&self, arg: Self::Y<'b>); } +// We require bounds when the GAT appears in the inputs +trait Input { + type Item<'a>; + //~^ missing required + fn takes_item<'a>(&'a self, item: Self::Item<'a>); +} + +// We don't require bounds when the GAT appears in the where clauses +trait WhereClause { + type Item<'a>; + fn takes_item<'a>(&'a self) where Self::Item<'a>: ; +} + fn main() {} diff --git a/src/test/ui/generic-associated-types/self-outlives-lint.stderr b/src/test/ui/generic-associated-types/self-outlives-lint.stderr index fdb1f50a776..a43b35bd79c 100644 --- a/src/test/ui/generic-associated-types/self-outlives-lint.stderr +++ b/src/test/ui/generic-associated-types/self-outlives-lint.stderr @@ -163,5 +163,16 @@ LL | type Fut<'out>; = note: this bound is currently required to ensure that impls have maximum flexibility = note: we are soliciting feedback, see issue #87479 for more information -error: aborting due to 15 previous errors +error: missing required bound on `Item` + --> $DIR/self-outlives-lint.rs:215:5 + | +LL | type Item<'a>; + | ^^^^^^^^^^^^^- + | | + | help: add the required where clause: `where Self: 'a` + | + = note: this bound is currently required to ensure that impls have maximum flexibility + = note: we are soliciting feedback, see issue #87479 for more information + +error: aborting due to 16 previous errors -- cgit 1.4.1-3-g733a5 From 28b6373b1d4f6fd58f3435da2551021034c4a9d4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 3 Aug 2022 03:16:31 +0000 Subject: Fall back when relating two opaques by substs in MIR typeck --- compiler/rustc_infer/src/infer/nll_relate/mod.rs | 54 +++++++++++++----------- src/test/ui/impl-trait/issue-100075-2.rs | 8 ++++ src/test/ui/impl-trait/issue-100075-2.stderr | 24 +++++++++++ src/test/ui/impl-trait/issue-100075.rs | 21 +++++++++ src/test/ui/impl-trait/issue-100075.stderr | 12 ++++++ 5 files changed, 95 insertions(+), 24 deletions(-) create mode 100644 src/test/ui/impl-trait/issue-100075-2.rs create mode 100644 src/test/ui/impl-trait/issue-100075-2.stderr create mode 100644 src/test/ui/impl-trait/issue-100075.rs create mode 100644 src/test/ui/impl-trait/issue-100075.stderr diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index bab4f3e9e36..324aef9c01f 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -396,6 +396,32 @@ where generalizer.relate(value, value) } + + fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) }; + let mut generalize = |ty, ty_is_expected| { + let var = self.infcx.next_ty_var_id_in_universe( + TypeVariableOrigin { + kind: TypeVariableOriginKind::MiscVariable, + span: self.delegate.span(), + }, + ty::UniverseIndex::ROOT, + ); + if ty_is_expected { + self.relate_ty_var((ty, var)) + } else { + self.relate_ty_var((var, ty)) + } + }; + let (a, b) = match (a.kind(), b.kind()) { + (&ty::Opaque(..), _) => (a, generalize(b, false)?), + (_, &ty::Opaque(..)) => (generalize(a, true)?, b), + _ => unreachable!(), + }; + self.delegate.register_opaque_type(a, b, true)?; + trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated"); + Ok(a) + } } /// When we instantiate an inference variable with a value in @@ -572,32 +598,12 @@ where (&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)), (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => { - self.infcx.super_combine_tys(self, a, b) + infcx.commit_if_ok(|_| infcx.super_combine_tys(self, a, b)).or_else(|err| { + if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) } + }) } (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..)) if did.is_local() => { - let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) }; - let mut generalize = |ty, ty_is_expected| { - let var = infcx.next_ty_var_id_in_universe( - TypeVariableOrigin { - kind: TypeVariableOriginKind::MiscVariable, - span: self.delegate.span(), - }, - ty::UniverseIndex::ROOT, - ); - if ty_is_expected { - self.relate_ty_var((ty, var)) - } else { - self.relate_ty_var((var, ty)) - } - }; - let (a, b) = match (a.kind(), b.kind()) { - (&ty::Opaque(..), _) => (a, generalize(b, false)?), - (_, &ty::Opaque(..)) => (generalize(a, true)?, b), - _ => unreachable!(), - }; - self.delegate.register_opaque_type(a, b, true)?; - trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated"); - Ok(a) + self.relate_opaques(a, b) } (&ty::Projection(projection_ty), _) diff --git a/src/test/ui/impl-trait/issue-100075-2.rs b/src/test/ui/impl-trait/issue-100075-2.rs new file mode 100644 index 00000000000..cf059af1925 --- /dev/null +++ b/src/test/ui/impl-trait/issue-100075-2.rs @@ -0,0 +1,8 @@ +fn opaque(t: T) -> impl Sized { + //~^ ERROR cannot resolve opaque type + //~| WARNING function cannot return without recursing + opaque(Some(t)) +} + +#[allow(dead_code)] +fn main() {} diff --git a/src/test/ui/impl-trait/issue-100075-2.stderr b/src/test/ui/impl-trait/issue-100075-2.stderr new file mode 100644 index 00000000000..5a1f1a97d04 --- /dev/null +++ b/src/test/ui/impl-trait/issue-100075-2.stderr @@ -0,0 +1,24 @@ +warning: function cannot return without recursing + --> $DIR/issue-100075-2.rs:1:1 + | +LL | fn opaque(t: T) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +... +LL | opaque(Some(t)) + | --------------- recursive call site + | + = note: `#[warn(unconditional_recursion)]` on by default + = help: a `loop` may express intention better if this is on purpose + +error[E0720]: cannot resolve opaque type + --> $DIR/issue-100075-2.rs:1:23 + | +LL | fn opaque(t: T) -> impl Sized { + | ^^^^^^^^^^ recursive opaque type +... +LL | opaque(Some(t)) + | --------------- returning here with type `impl Sized` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0720`. diff --git a/src/test/ui/impl-trait/issue-100075.rs b/src/test/ui/impl-trait/issue-100075.rs new file mode 100644 index 00000000000..ea30abb4855 --- /dev/null +++ b/src/test/ui/impl-trait/issue-100075.rs @@ -0,0 +1,21 @@ +trait Marker {} +impl Marker for T {} + +fn maybe( + _t: T, +) -> Option< + //removing the line below makes it compile + &'static T, +> { + None +} + +fn _g(t: &'static T) -> &'static impl Marker { + //~^ ERROR cannot resolve opaque type + if let Some(t) = maybe(t) { + return _g(t); + } + todo!() +} + +fn main() {} diff --git a/src/test/ui/impl-trait/issue-100075.stderr b/src/test/ui/impl-trait/issue-100075.stderr new file mode 100644 index 00000000000..267ecfdaed1 --- /dev/null +++ b/src/test/ui/impl-trait/issue-100075.stderr @@ -0,0 +1,12 @@ +error[E0720]: cannot resolve opaque type + --> $DIR/issue-100075.rs:13:37 + | +LL | fn _g(t: &'static T) -> &'static impl Marker { + | ^^^^^^^^^^^ recursive opaque type +... +LL | return _g(t); + | ----- returning here with type `&impl Marker` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0720`. -- cgit 1.4.1-3-g733a5 From 534426d0f3d12b735b0018bcf268b08a09cc09b8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 10 Aug 2022 03:36:05 +0000 Subject: Delay a bug if we try and fail to relate an opaque to itself in TypeRelating --- compiler/rustc_infer/src/infer/nll_relate/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 324aef9c01f..e7e93116a66 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -599,6 +599,10 @@ where (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => { infcx.commit_if_ok(|_| infcx.super_combine_tys(self, a, b)).or_else(|err| { + self.tcx().sess.delay_span_bug( + self.delegate.span(), + "failure to relate an opaque to itself should result in an error later on", + ); if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) } }) } -- cgit 1.4.1-3-g733a5 From a7443a61ab2581ec9cdd3be08807ce599a5d56b8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 10 Aug 2022 15:06:17 +0000 Subject: Move some code into codegen_fn_content --- src/base.rs | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/base.rs b/src/base.rs index 2c04cf47268..439b636031b 100644 --- a/src/base.rs +++ b/src/base.rs @@ -82,27 +82,7 @@ pub(crate) fn codegen_fn<'tcx>( next_ssa_var: 0, }; - let arg_uninhabited = fx - .mir - .args_iter() - .any(|arg| fx.layout_of(fx.monomorphize(fx.mir.local_decls[arg].ty)).abi.is_uninhabited()); - - if !crate::constant::check_constants(&mut fx) { - fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]); - fx.bcx.switch_to_block(fx.block_map[START_BLOCK]); - // compilation should have been aborted - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); - } else if arg_uninhabited { - fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]); - fx.bcx.switch_to_block(fx.block_map[START_BLOCK]); - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); - } else { - tcx.sess.time("codegen clif ir", || { - tcx.sess - .time("codegen prelude", || crate::abi::codegen_fn_prelude(&mut fx, start_block)); - codegen_fn_content(&mut fx); - }); - } + tcx.sess.time("codegen clif ir", || codegen_fn_body(&mut fx, start_block)); // Recover all necessary data from fx, before accessing func will prevent future access to it. let instance = fx.instance; @@ -269,7 +249,27 @@ pub(crate) fn verify_func( }); } -fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) { +fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { + if !crate::constant::check_constants(fx) { + fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]); + fx.bcx.switch_to_block(fx.block_map[START_BLOCK]); + // compilation should have been aborted + fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + return; + } + + let arg_uninhabited = fx + .mir + .args_iter() + .any(|arg| fx.layout_of(fx.monomorphize(fx.mir.local_decls[arg].ty)).abi.is_uninhabited()); + if arg_uninhabited { + fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]); + fx.bcx.switch_to_block(fx.block_map[START_BLOCK]); + fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + return; + } + fx.tcx.sess.time("codegen prelude", || crate::abi::codegen_fn_prelude(fx, start_block)); + for (bb, bb_data) in fx.mir.basic_blocks().iter_enumerated() { let block = fx.get_block(bb); fx.bcx.switch_to_block(block); -- cgit 1.4.1-3-g733a5 From a10da0f76898eca1ebd398748b98b205f4284297 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 10 Aug 2022 18:29:46 +0000 Subject: Split non-compile parts of codegen_fn out into a separate function The new codegen_and_compile_fn function only calls codegen_fn and then compile_fn. This makes it possible for both parts to be called separately by the driver. --- src/base.rs | 67 ++++++++++++++++++++++++++++++++++--------------------- src/driver/aot.rs | 6 ++--- src/driver/jit.rs | 6 +++-- 3 files changed, 49 insertions(+), 30 deletions(-) diff --git a/src/base.rs b/src/base.rs index 439b636031b..8e3f905166b 100644 --- a/src/base.rs +++ b/src/base.rs @@ -5,6 +5,7 @@ use rustc_index::vec::IndexVec; use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::print::with_no_trimmed_paths; +use rustc_middle::ty::SymbolName; use indexmap::IndexSet; @@ -12,17 +13,39 @@ use crate::constant::ConstantCx; use crate::prelude::*; use crate::pretty_clif::CommentWriter; -pub(crate) fn codegen_fn<'tcx>( +struct CodegenedFunction<'tcx> { + instance: Instance<'tcx>, + symbol_name: SymbolName<'tcx>, + func_id: FuncId, + func: Function, + clif_comments: CommentWriter, + source_info_set: IndexSet, + local_map: IndexVec>, +} + +pub(crate) fn codegen_and_compile_fn<'tcx>( cx: &mut crate::CodegenCx<'tcx>, module: &mut dyn Module, instance: Instance<'tcx>, ) { let tcx = cx.tcx; - let _inst_guard = crate::PrintOnPanic(|| format!("{:?} {}", instance, tcx.symbol_name(instance).name)); + + let codegened_func = codegen_fn(cx, module, instance); + + compile_fn(cx, module, codegened_func); +} + +fn codegen_fn<'tcx>( + cx: &mut crate::CodegenCx<'tcx>, + module: &mut dyn Module, + instance: Instance<'tcx>, +) -> CodegenedFunction<'tcx> { debug_assert!(!instance.substs.needs_infer()); + let tcx = cx.tcx; + let mir = tcx.instance_mir(instance.def); let _mir_guard = crate::PrintOnPanic(|| { let mut buf = Vec::new(); @@ -104,36 +127,30 @@ pub(crate) fn codegen_fn<'tcx>( // Verify function verify_func(tcx, &clif_comments, &func); - compile_fn( - cx, - module, + CodegenedFunction { instance, - symbol_name.name, + symbol_name, func_id, func, clif_comments, source_info_set, local_map, - ); + } } fn compile_fn<'tcx>( cx: &mut crate::CodegenCx<'tcx>, module: &mut dyn Module, - instance: Instance<'tcx>, - symbol_name: &str, - func_id: FuncId, - func: Function, - mut clif_comments: CommentWriter, - source_info_set: IndexSet, - local_map: IndexVec>, + codegened_func: CodegenedFunction<'tcx>, ) { let tcx = cx.tcx; + let mut clif_comments = codegened_func.clif_comments; + // Store function in context let context = &mut cx.cached_context; context.clear(); - context.func = func; + context.func = codegened_func.func; // If the return block is not reachable, then the SSA builder may have inserted an `iconst.i128` // instruction, which doesn't have an encoding. @@ -150,7 +167,7 @@ fn compile_fn<'tcx>( crate::optimize::optimize_function( tcx, module.isa(), - instance, + codegened_func.instance, context, &mut clif_comments, ); @@ -186,7 +203,7 @@ fn compile_fn<'tcx>( // Define function tcx.sess.time("define function", || { context.want_disasm = crate::pretty_clif::should_write_ir(tcx); - module.define_function(func_id, context).unwrap(); + module.define_function(codegened_func.func_id, context).unwrap(); }); // Write optimized function to file for debugging @@ -194,7 +211,7 @@ fn compile_fn<'tcx>( tcx, "opt", module.isa(), - instance, + codegened_func.instance, &context.func, &clif_comments, ); @@ -202,7 +219,7 @@ fn compile_fn<'tcx>( if let Some(disasm) = &context.mach_compile_result.as_ref().unwrap().disasm { crate::pretty_clif::write_ir_file( tcx, - || format!("{}.vcode", tcx.symbol_name(instance).name), + || format!("{}.vcode", tcx.symbol_name(codegened_func.instance).name), |file| file.write_all(disasm.as_bytes()), ) } @@ -214,16 +231,16 @@ fn compile_fn<'tcx>( tcx.sess.time("generate debug info", || { if let Some(debug_context) = debug_context { debug_context.define_function( - instance, - func_id, - symbol_name, + codegened_func.instance, + codegened_func.func_id, + codegened_func.symbol_name.name, isa, context, - &source_info_set, - local_map, + &codegened_func.source_info_set, + codegened_func.local_map, ); } - unwind_context.add_function(func_id, &context, isa); + unwind_context.add_function(codegened_func.func_id, &context, isa); }); } diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 3cd1ef5639e..802e8ebd6f6 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -131,9 +131,9 @@ fn module_codegen( for (mono_item, _) in mono_items { match mono_item { MonoItem::Fn(inst) => { - cx.tcx - .sess - .time("codegen fn", || crate::base::codegen_fn(&mut cx, &mut module, inst)); + cx.tcx.sess.time("codegen fn", || { + crate::base::codegen_and_compile_fn(&mut cx, &mut module, inst) + }); } MonoItem::Static(def_id) => crate::constant::codegen_static(tcx, &mut module, def_id), MonoItem::GlobalAsm(item_id) => { diff --git a/src/driver/jit.rs b/src/driver/jit.rs index a56a9100059..a7ea2b182ab 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -129,7 +129,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { CodegenMode::Aot => unreachable!(), CodegenMode::Jit => { cx.tcx.sess.time("codegen fn", || { - crate::base::codegen_fn(&mut cx, &mut jit_module, inst) + crate::base::codegen_and_compile_fn(&mut cx, &mut jit_module, inst) }); } CodegenMode::JitLazy => codegen_shim(&mut cx, &mut jit_module, inst), @@ -259,7 +259,9 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> false, Symbol::intern("dummy_cgu_name"), ); - tcx.sess.time("codegen fn", || crate::base::codegen_fn(&mut cx, jit_module, instance)); + tcx.sess.time("codegen fn", || { + crate::base::codegen_and_compile_fn(&mut cx, jit_module, instance) + }); assert!(cx.global_asm.is_empty()); jit_module.finalize_definitions(); -- cgit 1.4.1-3-g733a5 From 8a336a2ae1ebcbafb47d5c9c8b30ea956aaa58f9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 10 Aug 2022 18:47:05 +0000 Subject: Move cached_context out of CodegenCx --- src/base.rs | 15 +++++++++------ src/driver/aot.rs | 8 +++++++- src/driver/jit.rs | 33 ++++++++++++++++++++++++++------- src/lib.rs | 2 -- 4 files changed, 42 insertions(+), 16 deletions(-) diff --git a/src/base.rs b/src/base.rs index 8e3f905166b..c68d33465bc 100644 --- a/src/base.rs +++ b/src/base.rs @@ -25,6 +25,7 @@ struct CodegenedFunction<'tcx> { pub(crate) fn codegen_and_compile_fn<'tcx>( cx: &mut crate::CodegenCx<'tcx>, + cached_context: &mut Context, module: &mut dyn Module, instance: Instance<'tcx>, ) { @@ -32,13 +33,15 @@ pub(crate) fn codegen_and_compile_fn<'tcx>( let _inst_guard = crate::PrintOnPanic(|| format!("{:?} {}", instance, tcx.symbol_name(instance).name)); - let codegened_func = codegen_fn(cx, module, instance); + let cached_func = std::mem::replace(&mut cached_context.func, Function::new()); + let codegened_func = codegen_fn(cx, cached_func, module, instance); - compile_fn(cx, module, codegened_func); + compile_fn(cx, cached_context, module, codegened_func); } fn codegen_fn<'tcx>( cx: &mut crate::CodegenCx<'tcx>, + cached_func: Function, module: &mut dyn Module, instance: Instance<'tcx>, ) -> CodegenedFunction<'tcx> { @@ -61,11 +64,10 @@ fn codegen_fn<'tcx>( let sig = get_function_sig(tcx, module.isa().triple(), instance); let func_id = module.declare_function(symbol_name.name, Linkage::Local, &sig).unwrap(); - cx.cached_context.clear(); - // Make the FunctionBuilder let mut func_ctx = FunctionBuilderContext::new(); - let mut func = std::mem::replace(&mut cx.cached_context.func, Function::new()); + let mut func = cached_func; + func.clear(); func.name = ExternalName::user(0, func_id.as_u32()); func.signature = sig; func.collect_debug_info(); @@ -140,6 +142,7 @@ fn codegen_fn<'tcx>( fn compile_fn<'tcx>( cx: &mut crate::CodegenCx<'tcx>, + cached_context: &mut Context, module: &mut dyn Module, codegened_func: CodegenedFunction<'tcx>, ) { @@ -148,7 +151,7 @@ fn compile_fn<'tcx>( let mut clif_comments = codegened_func.clif_comments; // Store function in context - let context = &mut cx.cached_context; + let context = cached_context; context.clear(); context.func = codegened_func.func; diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 802e8ebd6f6..6aa28637943 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -128,11 +128,17 @@ fn module_codegen( cgu_name, ); super::predefine_mono_items(tcx, &mut module, &mono_items); + let mut cached_context = Context::new(); for (mono_item, _) in mono_items { match mono_item { MonoItem::Fn(inst) => { cx.tcx.sess.time("codegen fn", || { - crate::base::codegen_and_compile_fn(&mut cx, &mut module, inst) + crate::base::codegen_and_compile_fn( + &mut cx, + &mut cached_context, + &mut module, + inst, + ) }); } MonoItem::Static(def_id) => crate::constant::codegen_static(tcx, &mut module, def_id), diff --git a/src/driver/jit.rs b/src/driver/jit.rs index a7ea2b182ab..1b046d7ec6e 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -111,6 +111,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { &backend_config, matches!(backend_config.codegen_mode, CodegenMode::JitLazy), ); + let mut cached_context = Context::new(); let (_, cgus) = tcx.collect_and_partition_mono_items(()); let mono_items = cgus @@ -129,10 +130,17 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { CodegenMode::Aot => unreachable!(), CodegenMode::Jit => { cx.tcx.sess.time("codegen fn", || { - crate::base::codegen_and_compile_fn(&mut cx, &mut jit_module, inst) + crate::base::codegen_and_compile_fn( + &mut cx, + &mut cached_context, + &mut jit_module, + inst, + ) }); } - CodegenMode::JitLazy => codegen_shim(&mut cx, &mut jit_module, inst), + CodegenMode::JitLazy => { + codegen_shim(&mut cx, &mut cached_context, &mut jit_module, inst) + } }, MonoItem::Static(def_id) => { crate::constant::codegen_static(tcx, &mut jit_module, def_id); @@ -260,7 +268,12 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> Symbol::intern("dummy_cgu_name"), ); tcx.sess.time("codegen fn", || { - crate::base::codegen_and_compile_fn(&mut cx, jit_module, instance) + crate::base::codegen_and_compile_fn( + &mut cx, + &mut Context::new(), + jit_module, + instance, + ) }); assert!(cx.global_asm.is_empty()); @@ -336,7 +349,12 @@ fn load_imported_symbols_for_jit( imported_symbols } -fn codegen_shim<'tcx>(cx: &mut CodegenCx<'tcx>, module: &mut JITModule, inst: Instance<'tcx>) { +fn codegen_shim<'tcx>( + cx: &mut CodegenCx<'tcx>, + cached_context: &mut Context, + module: &mut JITModule, + inst: Instance<'tcx>, +) { let tcx = cx.tcx; let pointer_type = module.target_config().pointer_type(); @@ -359,8 +377,9 @@ fn codegen_shim<'tcx>(cx: &mut CodegenCx<'tcx>, module: &mut JITModule, inst: In ) .unwrap(); - cx.cached_context.clear(); - let trampoline = &mut cx.cached_context.func; + let context = cached_context; + context.clear(); + let trampoline = &mut context.func; trampoline.signature = sig.clone(); let mut builder_ctx = FunctionBuilderContext::new(); @@ -383,5 +402,5 @@ fn codegen_shim<'tcx>(cx: &mut CodegenCx<'tcx>, module: &mut JITModule, inst: In let ret_vals = trampoline_builder.func.dfg.inst_results(call_inst).to_vec(); trampoline_builder.ins().return_(&ret_vals); - module.define_function(func_id, &mut cx.cached_context).unwrap(); + module.define_function(func_id, context).unwrap(); } diff --git a/src/lib.rs b/src/lib.rs index bb0793b1deb..a3f8cc4dfa3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -123,7 +123,6 @@ struct CodegenCx<'tcx> { tcx: TyCtxt<'tcx>, global_asm: String, inline_asm_index: Cell, - cached_context: Context, debug_context: Option>, unwind_context: UnwindContext, cgu_name: Symbol, @@ -150,7 +149,6 @@ impl<'tcx> CodegenCx<'tcx> { tcx, global_asm: String::new(), inline_asm_index: Cell::new(0), - cached_context: Context::new(), debug_context, unwind_context, cgu_name, -- cgit 1.4.1-3-g733a5 From 07bcd111f8d3b60dbc3722215c78f25372a11c6f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 11 Aug 2022 13:38:07 +0000 Subject: Return ModuleCodegenResult from reuse_workproduct_for_cgu --- src/driver/aot.rs | 60 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 6aa28637943..6f1732f9707 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -79,11 +79,7 @@ fn emit_module( ) } -fn reuse_workproduct_for_cgu( - tcx: TyCtxt<'_>, - cgu: &CodegenUnit<'_>, - work_products: &mut FxHashMap, -) -> CompiledModule { +fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCodegenResult { let work_product = cgu.previous_work_product(tcx); let obj_out = tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str())); let source_file = rustc_incremental::in_incr_comp_dir_sess( @@ -99,15 +95,16 @@ fn reuse_workproduct_for_cgu( )); } - work_products.insert(cgu.work_product_id(), work_product); - - CompiledModule { - name: cgu.name().to_string(), - kind: ModuleKind::Regular, - object: Some(obj_out), - dwarf_object: None, - bytecode: None, - } + ModuleCodegenResult( + CompiledModule { + name: cgu.name().to_string(), + kind: ModuleKind::Regular, + object: Some(obj_out), + dwarf_object: None, + bytecode: None, + }, + Some((cgu.work_product_id(), work_product)), + ) } fn module_codegen( @@ -215,26 +212,31 @@ pub(crate) fn run_aot( let modules = super::time(tcx, backend_config.display_cg_time, "codegen mono items", || { cgus.iter() .map(|cgu| { - let cgu_reuse = determine_cgu_reuse(tcx, cgu); + let cgu_reuse = if backend_config.disable_incr_cache { + CguReuse::No + } else { + determine_cgu_reuse(tcx, cgu) + }; tcx.sess.cgu_reuse_tracker.set_actual_reuse(cgu.name().as_str(), cgu_reuse); - match cgu_reuse { - _ if backend_config.disable_incr_cache => {} - CguReuse::No => {} - CguReuse::PreLto => { - return reuse_workproduct_for_cgu(tcx, &*cgu, &mut work_products); + let module_codegen_result = match cgu_reuse { + CguReuse::No => { + let dep_node = cgu.codegen_dep_node(tcx); + tcx.dep_graph + .with_task( + dep_node, + tcx, + (backend_config.clone(), cgu.name()), + module_codegen, + Some(rustc_middle::dep_graph::hash_result), + ) + .0 } + CguReuse::PreLto => reuse_workproduct_for_cgu(tcx, &*cgu), CguReuse::PostLto => unreachable!(), - } + }; - let dep_node = cgu.codegen_dep_node(tcx); - let (ModuleCodegenResult(module, work_product), _) = tcx.dep_graph.with_task( - dep_node, - tcx, - (backend_config.clone(), cgu.name()), - module_codegen, - Some(rustc_middle::dep_graph::hash_result), - ); + let ModuleCodegenResult(module, work_product) = module_codegen_result; if let Some((id, product)) = work_product { work_products.insert(id, product); -- cgit 1.4.1-3-g733a5 From c5adc96532205a12c94c1407e6b6b35f7c7a2b64 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 11 Aug 2022 13:49:08 +0000 Subject: Introduce OngoingCodegen type --- src/driver/aot.rs | 67 ++++++++++++++++++++++++++++++++++++++----------------- src/lib.rs | 4 +--- 2 files changed, 47 insertions(+), 24 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 6f1732f9707..c417de04ab4 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -27,6 +27,41 @@ impl HashStable for ModuleCodegenResult { } } +pub(crate) struct OngoingCodegen { + modules: Vec, + allocator_module: Option, + metadata_module: Option, + metadata: EncodedMetadata, + crate_info: CrateInfo, + work_products: FxHashMap, +} + +impl OngoingCodegen { + pub(crate) fn join(self) -> (CodegenResults, FxHashMap) { + let mut work_products = self.work_products; + let mut modules = vec![]; + + for module_codegen_result in self.modules { + let ModuleCodegenResult(module, work_product) = module_codegen_result; + if let Some((work_product_id, work_product)) = work_product { + work_products.insert(work_product_id, work_product); + } + modules.push(module); + } + + ( + CodegenResults { + modules, + allocator_module: self.allocator_module, + metadata_module: self.metadata_module, + metadata: self.metadata, + crate_info: self.crate_info, + }, + work_products, + ) + } +} + fn make_module(sess: &Session, isa: Box, name: String) -> ObjectModule { let mut builder = ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap(); @@ -192,9 +227,7 @@ pub(crate) fn run_aot( backend_config: BackendConfig, metadata: EncodedMetadata, need_metadata_module: bool, -) -> Box<(CodegenResults, FxHashMap)> { - let mut work_products = FxHashMap::default(); - +) -> Box { let cgus = if tcx.sess.opts.output_types.should_codegen() { tcx.collect_and_partition_mono_items(()).1 } else { @@ -219,7 +252,7 @@ pub(crate) fn run_aot( }; tcx.sess.cgu_reuse_tracker.set_actual_reuse(cgu.name().as_str(), cgu_reuse); - let module_codegen_result = match cgu_reuse { + match cgu_reuse { CguReuse::No => { let dep_node = cgu.codegen_dep_node(tcx); tcx.dep_graph @@ -234,21 +267,15 @@ pub(crate) fn run_aot( } CguReuse::PreLto => reuse_workproduct_for_cgu(tcx, &*cgu), CguReuse::PostLto => unreachable!(), - }; - - let ModuleCodegenResult(module, work_product) = module_codegen_result; - - if let Some((id, product)) = work_product { - work_products.insert(id, product); } - - module }) .collect::>() }); tcx.sess.abort_if_errors(); + let mut work_products = FxHashMap::default(); + let isa = crate::build_isa(tcx.sess, &backend_config); let mut allocator_module = make_module(tcx.sess, isa, "allocator_shim".to_string()); assert_eq!(pointer_ty(tcx), allocator_module.target_config().pointer_type()); @@ -316,16 +343,14 @@ pub(crate) fn run_aot( } .to_owned(); - Box::new(( - CodegenResults { - modules, - allocator_module, - metadata_module, - metadata, - crate_info: CrateInfo::new(tcx, target_cpu), - }, + Box::new(OngoingCodegen { + modules, + allocator_module, + metadata_module, + metadata, + crate_info: CrateInfo::new(tcx, target_cpu), work_products, - )) + }) } fn codegen_global_asm(tcx: TyCtxt<'_>, cgu_name: &str, global_asm: &str) { diff --git a/src/lib.rs b/src/lib.rs index a3f8cc4dfa3..49d10012c4f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -211,9 +211,7 @@ impl CodegenBackend for CraneliftCodegenBackend { _sess: &Session, _outputs: &OutputFilenames, ) -> Result<(CodegenResults, FxHashMap), ErrorGuaranteed> { - Ok(*ongoing_codegen - .downcast::<(CodegenResults, FxHashMap)>() - .unwrap()) + Ok(ongoing_codegen.downcast::().unwrap().join()) } fn link( -- cgit 1.4.1-3-g733a5 From 7cc97ebcbb3fe637e2467f2e4fc45d94dae013e8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 12 Aug 2022 09:11:47 +0000 Subject: Extract global_asm module --- src/driver/aot.rs | 109 +------------------------------------------------- src/global_asm.rs | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 3 files changed, 119 insertions(+), 107 deletions(-) create mode 100644 src/global_asm.rs diff --git a/src/driver/aot.rs b/src/driver/aot.rs index c417de04ab4..6482dce2746 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -1,9 +1,6 @@ //! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a //! standalone executable. -use std::path::PathBuf; - -use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file; use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -175,23 +172,7 @@ fn module_codegen( } MonoItem::Static(def_id) => crate::constant::codegen_static(tcx, &mut module, def_id), MonoItem::GlobalAsm(item_id) => { - let item = cx.tcx.hir().item(item_id); - if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind { - if !asm.options.contains(InlineAsmOptions::ATT_SYNTAX) { - cx.global_asm.push_str("\n.intel_syntax noprefix\n"); - } else { - cx.global_asm.push_str("\n.att_syntax\n"); - } - for piece in asm.template { - match *piece { - InlineAsmTemplatePiece::String(ref s) => cx.global_asm.push_str(s), - InlineAsmTemplatePiece::Placeholder { .. } => todo!(), - } - } - cx.global_asm.push_str("\n.att_syntax\n\n"); - } else { - bug!("Expected GlobalAsm found {:?}", item); - } + crate::global_asm::codegen_global_asm_item(tcx, &mut cx.global_asm, item_id); } } } @@ -217,7 +198,7 @@ fn module_codegen( ) }); - codegen_global_asm(tcx, cgu.name().as_str(), &cx.global_asm); + crate::global_asm::compile_global_asm(tcx, cgu.name().as_str(), &cx.global_asm); codegen_result } @@ -353,92 +334,6 @@ pub(crate) fn run_aot( }) } -fn codegen_global_asm(tcx: TyCtxt<'_>, cgu_name: &str, global_asm: &str) { - use std::io::Write; - use std::process::{Command, Stdio}; - - if global_asm.is_empty() { - return; - } - - if cfg!(not(feature = "inline_asm")) - || tcx.sess.target.is_like_osx - || tcx.sess.target.is_like_windows - { - if global_asm.contains("__rust_probestack") { - return; - } - - // FIXME fix linker error on macOS - if cfg!(not(feature = "inline_asm")) { - tcx.sess.fatal( - "asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift", - ); - } else { - tcx.sess.fatal("asm! and global_asm! are not yet supported on macOS and Windows"); - } - } - - let assembler = crate::toolchain::get_toolchain_binary(tcx.sess, "as"); - let linker = crate::toolchain::get_toolchain_binary(tcx.sess, "ld"); - - // Remove all LLVM style comments - let global_asm = global_asm - .lines() - .map(|line| if let Some(index) = line.find("//") { &line[0..index] } else { line }) - .collect::>() - .join("\n"); - - let output_object_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu_name)); - - // Assemble `global_asm` - let global_asm_object_file = add_file_stem_postfix(output_object_file.clone(), ".asm"); - let mut child = Command::new(assembler) - .arg("-o") - .arg(&global_asm_object_file) - .stdin(Stdio::piped()) - .spawn() - .expect("Failed to spawn `as`."); - child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap(); - let status = child.wait().expect("Failed to wait for `as`."); - if !status.success() { - tcx.sess.fatal(&format!("Failed to assemble `{}`", global_asm)); - } - - // Link the global asm and main object file together - let main_object_file = add_file_stem_postfix(output_object_file.clone(), ".main"); - std::fs::rename(&output_object_file, &main_object_file).unwrap(); - let status = Command::new(linker) - .arg("-r") // Create a new object file - .arg("-o") - .arg(output_object_file) - .arg(&main_object_file) - .arg(&global_asm_object_file) - .status() - .unwrap(); - if !status.success() { - tcx.sess.fatal(&format!( - "Failed to link `{}` and `{}` together", - main_object_file.display(), - global_asm_object_file.display(), - )); - } - - std::fs::remove_file(global_asm_object_file).unwrap(); - std::fs::remove_file(main_object_file).unwrap(); -} - -fn add_file_stem_postfix(mut path: PathBuf, postfix: &str) -> PathBuf { - let mut new_filename = path.file_stem().unwrap().to_owned(); - new_filename.push(postfix); - if let Some(extension) = path.extension() { - new_filename.push("."); - new_filename.push(extension); - } - path.set_file_name(new_filename); - path -} - // Adapted from https://github.com/rust-lang/rust/blob/303d8aff6092709edd4dbd35b1c88e9aa40bf6d8/src/librustc_codegen_ssa/base.rs#L922-L953 fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> CguReuse { if !tcx.dep_graph.is_fully_enabled() { diff --git a/src/global_asm.rs b/src/global_asm.rs new file mode 100644 index 00000000000..5962a86a686 --- /dev/null +++ b/src/global_asm.rs @@ -0,0 +1,116 @@ +//! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a +//! standalone executable. + +use std::path::PathBuf; + +use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; +use rustc_hir::ItemId; +use rustc_session::config::OutputType; + +use crate::prelude::*; + +pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) { + let item = tcx.hir().item(item_id); + if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind { + if !asm.options.contains(InlineAsmOptions::ATT_SYNTAX) { + global_asm.push_str("\n.intel_syntax noprefix\n"); + } else { + global_asm.push_str("\n.att_syntax\n"); + } + for piece in asm.template { + match *piece { + InlineAsmTemplatePiece::String(ref s) => global_asm.push_str(s), + InlineAsmTemplatePiece::Placeholder { .. } => todo!(), + } + } + global_asm.push_str("\n.att_syntax\n\n"); + } else { + bug!("Expected GlobalAsm found {:?}", item); + } +} + +pub(crate) fn compile_global_asm(tcx: TyCtxt<'_>, cgu_name: &str, global_asm: &str) { + use std::io::Write; + use std::process::{Command, Stdio}; + + if global_asm.is_empty() { + return; + } + + if cfg!(not(feature = "inline_asm")) + || tcx.sess.target.is_like_osx + || tcx.sess.target.is_like_windows + { + if global_asm.contains("__rust_probestack") { + return; + } + + // FIXME fix linker error on macOS + if cfg!(not(feature = "inline_asm")) { + tcx.sess.fatal( + "asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift", + ); + } else { + tcx.sess.fatal("asm! and global_asm! are not yet supported on macOS and Windows"); + } + } + + let assembler = crate::toolchain::get_toolchain_binary(tcx.sess, "as"); + let linker = crate::toolchain::get_toolchain_binary(tcx.sess, "ld"); + + // Remove all LLVM style comments + let global_asm = global_asm + .lines() + .map(|line| if let Some(index) = line.find("//") { &line[0..index] } else { line }) + .collect::>() + .join("\n"); + + let output_object_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu_name)); + + // Assemble `global_asm` + let global_asm_object_file = add_file_stem_postfix(output_object_file.clone(), ".asm"); + let mut child = Command::new(assembler) + .arg("-o") + .arg(&global_asm_object_file) + .stdin(Stdio::piped()) + .spawn() + .expect("Failed to spawn `as`."); + child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap(); + let status = child.wait().expect("Failed to wait for `as`."); + if !status.success() { + tcx.sess.fatal(&format!("Failed to assemble `{}`", global_asm)); + } + + // Link the global asm and main object file together + let main_object_file = add_file_stem_postfix(output_object_file.clone(), ".main"); + std::fs::rename(&output_object_file, &main_object_file).unwrap(); + let status = Command::new(linker) + .arg("-r") // Create a new object file + .arg("-o") + .arg(output_object_file) + .arg(&main_object_file) + .arg(&global_asm_object_file) + .status() + .unwrap(); + if !status.success() { + tcx.sess.fatal(&format!( + "Failed to link `{}` and `{}` together", + main_object_file.display(), + global_asm_object_file.display(), + )); + } + + std::fs::remove_file(global_asm_object_file).unwrap(); + std::fs::remove_file(main_object_file).unwrap(); +} + +fn add_file_stem_postfix(mut path: PathBuf, postfix: &str) -> PathBuf { + let mut new_filename = path.file_stem().unwrap().to_owned(); + new_filename.push(postfix); + if let Some(extension) = path.extension() { + new_filename.push("."); + new_filename.push(extension); + } + path.set_file_name(new_filename); + path +} diff --git a/src/lib.rs b/src/lib.rs index 49d10012c4f..6ea160d26ce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,6 +56,7 @@ mod constant; mod debuginfo; mod discriminant; mod driver; +mod global_asm; mod inline_asm; mod intrinsics; mod linkage; -- cgit 1.4.1-3-g733a5 From 066f844fff7b6bf227c375a293fe15af88cf85ac Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 12 Aug 2022 09:28:41 +0000 Subject: Move some sess.fatal calls out of compile_global_asm --- src/driver/aot.rs | 5 ++++- src/global_asm.rs | 43 +++++++++++++++++++++++++++++-------------- src/toolchain.rs | 6 ++---- 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 6482dce2746..0816ebc4599 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -198,7 +198,10 @@ fn module_codegen( ) }); - crate::global_asm::compile_global_asm(tcx, cgu.name().as_str(), &cx.global_asm); + match crate::global_asm::compile_global_asm(tcx, cgu.name().as_str(), &cx.global_asm) { + Ok(()) => {} + Err(err) => tcx.sess.fatal(&err.to_string()), + } codegen_result } diff --git a/src/global_asm.rs b/src/global_asm.rs index 5962a86a686..5cd7abfdfb5 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -1,7 +1,9 @@ //! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a //! standalone executable. +use std::io::{self, Write}; use std::path::PathBuf; +use std::process::{Command, Stdio}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::ItemId; @@ -29,12 +31,13 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, } } -pub(crate) fn compile_global_asm(tcx: TyCtxt<'_>, cgu_name: &str, global_asm: &str) { - use std::io::Write; - use std::process::{Command, Stdio}; - +pub(crate) fn compile_global_asm( + tcx: TyCtxt<'_>, + cgu_name: &str, + global_asm: &str, +) -> io::Result<()> { if global_asm.is_empty() { - return; + return Ok(()); } if cfg!(not(feature = "inline_asm")) @@ -42,16 +45,20 @@ pub(crate) fn compile_global_asm(tcx: TyCtxt<'_>, cgu_name: &str, global_asm: &s || tcx.sess.target.is_like_windows { if global_asm.contains("__rust_probestack") { - return; + return Ok(()); } // FIXME fix linker error on macOS if cfg!(not(feature = "inline_asm")) { - tcx.sess.fatal( + return Err(io::Error::new( + io::ErrorKind::Unsupported, "asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift", - ); + )); } else { - tcx.sess.fatal("asm! and global_asm! are not yet supported on macOS and Windows"); + return Err(io::Error::new( + io::ErrorKind::Unsupported, + "asm! and global_asm! are not yet supported on macOS and Windows", + )); } } @@ -78,7 +85,10 @@ pub(crate) fn compile_global_asm(tcx: TyCtxt<'_>, cgu_name: &str, global_asm: &s child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap(); let status = child.wait().expect("Failed to wait for `as`."); if !status.success() { - tcx.sess.fatal(&format!("Failed to assemble `{}`", global_asm)); + return Err(io::Error::new( + io::ErrorKind::Other, + format!("Failed to assemble `{}`", global_asm), + )); } // Link the global asm and main object file together @@ -93,15 +103,20 @@ pub(crate) fn compile_global_asm(tcx: TyCtxt<'_>, cgu_name: &str, global_asm: &s .status() .unwrap(); if !status.success() { - tcx.sess.fatal(&format!( - "Failed to link `{}` and `{}` together", - main_object_file.display(), - global_asm_object_file.display(), + return Err(io::Error::new( + io::ErrorKind::Other, + format!( + "Failed to link `{}` and `{}` together", + main_object_file.display(), + global_asm_object_file.display(), + ), )); } std::fs::remove_file(global_asm_object_file).unwrap(); std::fs::remove_file(main_object_file).unwrap(); + + Ok(()) } fn add_file_stem_postfix(mut path: PathBuf, postfix: &str) -> PathBuf { diff --git a/src/toolchain.rs b/src/toolchain.rs index f86236ef3ea..b6b465e1f4e 100644 --- a/src/toolchain.rs +++ b/src/toolchain.rs @@ -8,10 +8,8 @@ use rustc_session::Session; /// Tries to infer the path of a binary for the target toolchain from the linker name. pub(crate) fn get_toolchain_binary(sess: &Session, tool: &str) -> PathBuf { let (mut linker, _linker_flavor) = linker_and_flavor(sess); - let linker_file_name = linker - .file_name() - .and_then(|name| name.to_str()) - .unwrap_or_else(|| sess.fatal("couldn't extract file name from specified linker")); + let linker_file_name = + linker.file_name().unwrap().to_str().expect("linker filename should be valid UTF-8"); if linker_file_name == "ld.lld" { if tool != "ld" { -- cgit 1.4.1-3-g733a5 From ee30cc8b204ed85bf3f843fb038d1d3e9c2fe8e2 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Tue, 26 Jul 2022 19:04:27 +0200 Subject: make some const prop tests unit-test --- src/test/mir-opt/const_prop/aggregate.main.ConstProp.diff | 2 +- src/test/mir-opt/const_prop/aggregate.rs | 1 + .../mir-opt/const_prop/array_index.main.ConstProp.32bit.diff | 7 ++++--- .../mir-opt/const_prop/array_index.main.ConstProp.64bit.diff | 7 ++++--- src/test/mir-opt/const_prop/array_index.rs | 1 + .../mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff | 10 ++++------ src/test/mir-opt/const_prop/bad_op_div_by_zero.rs | 1 + src/test/mir-opt/const_prop/boolean_identities.rs | 1 + src/test/mir-opt/const_prop/boxes.main.ConstProp.diff | 7 +++---- src/test/mir-opt/const_prop/boxes.rs | 1 + src/test/mir-opt/const_prop/cast.main.ConstProp.diff | 2 +- src/test/mir-opt/const_prop/cast.rs | 1 + src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff | 2 +- src/test/mir-opt/const_prop/checked_add.rs | 1 + .../const_prop/const_prop_fails_gracefully.main.ConstProp.diff | 6 +++--- src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs | 1 + src/test/mir-opt/const_prop/control-flow-simplification.rs | 7 ++++--- .../mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff | 2 +- .../mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff | 2 +- src/test/mir-opt/const_prop/discriminant.rs | 1 + src/test/mir-opt/const_prop/indirect.main.ConstProp.diff | 4 ++-- src/test/mir-opt/const_prop/indirect.rs | 1 + src/test/mir-opt/const_prop/issue-66971.rs | 1 + src/test/mir-opt/const_prop/issue-67019.rs | 1 + src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff | 2 +- src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff | 2 +- src/test/mir-opt/const_prop/mult_by_zero.rs | 1 + src/test/mir-opt/const_prop/mutable_variable.rs | 1 + src/test/mir-opt/const_prop/mutable_variable_aggregate.rs | 1 + .../mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs | 1 + ...mutable_variable_aggregate_partial_read.main.ConstProp.diff | 2 +- .../const_prop/mutable_variable_aggregate_partial_read.rs | 1 + .../const_prop/mutable_variable_no_prop.main.ConstProp.diff | 2 +- src/test/mir-opt/const_prop/mutable_variable_no_prop.rs | 1 + .../mutable_variable_unprop_assign.main.ConstProp.diff | 2 +- src/test/mir-opt/const_prop/mutable_variable_unprop_assign.rs | 1 + src/test/mir-opt/const_prop/optimizes_into_variable.rs | 1 + .../const_prop/read_immutable_static.main.ConstProp.diff | 4 ++-- src/test/mir-opt/const_prop/read_immutable_static.rs | 1 + .../mir-opt/const_prop/ref_deref_project.main.ConstProp.diff | 2 +- .../const_prop/ref_deref_project.main.PromoteTemps.diff | 2 +- src/test/mir-opt/const_prop/ref_deref_project.rs | 1 + 42 files changed, 60 insertions(+), 38 deletions(-) diff --git a/src/test/mir-opt/const_prop/aggregate.main.ConstProp.diff b/src/test/mir-opt/const_prop/aggregate.main.ConstProp.diff index 836443bf4d2..04378dbf374 100644 --- a/src/test/mir-opt/const_prop/aggregate.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/aggregate.main.ConstProp.diff @@ -24,7 +24,7 @@ + _1 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:28 StorageDead(_2); // scope 0 at $DIR/aggregate.rs:+1:27: +1:28 StorageDead(_3); // scope 0 at $DIR/aggregate.rs:+1:28: +1:29 - nop; // scope 0 at $DIR/aggregate.rs:+0:11: +2:2 + _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:11: +2:2 StorageDead(_1); // scope 0 at $DIR/aggregate.rs:+2:1: +2:2 return; // scope 0 at $DIR/aggregate.rs:+2:2: +2:2 } diff --git a/src/test/mir-opt/const_prop/aggregate.rs b/src/test/mir-opt/const_prop/aggregate.rs index 7a3b26a7317..493d0508a04 100644 --- a/src/test/mir-opt/const_prop/aggregate.rs +++ b/src/test/mir-opt/const_prop/aggregate.rs @@ -1,3 +1,4 @@ +// unit-test: ConstProp // compile-flags: -O // EMIT_MIR aggregate.main.ConstProp.diff diff --git a/src/test/mir-opt/const_prop/array_index.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/array_index.main.ConstProp.32bit.diff index bb9abdd1020..439b2a3e16b 100644 --- a/src/test/mir-opt/const_prop/array_index.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/array_index.main.ConstProp.32bit.diff @@ -18,11 +18,12 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; // scope 0 at $DIR/array_index.rs:+1:18: +1:30 StorageLive(_3); // scope 0 at $DIR/array_index.rs:+1:31: +1:32 _3 = const 2_usize; // scope 0 at $DIR/array_index.rs:+1:31: +1:32 - _4 = const 4_usize; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 +- _4 = Len(_2); // scope 0 at $DIR/array_index.rs:+1:18: +1:33 - _5 = Lt(_3, _4); // scope 0 at $DIR/array_index.rs:+1:18: +1:33 - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 ++ _4 = const 4_usize; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 + _5 = const true; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 ++ assert(const true, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 } bb1: { @@ -30,7 +31,7 @@ + _1 = const 2_u32; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 StorageDead(_3); // scope 0 at $DIR/array_index.rs:+1:33: +1:34 StorageDead(_2); // scope 0 at $DIR/array_index.rs:+1:33: +1:34 - nop; // scope 0 at $DIR/array_index.rs:+0:11: +2:2 + _0 = const (); // scope 0 at $DIR/array_index.rs:+0:11: +2:2 StorageDead(_1); // scope 0 at $DIR/array_index.rs:+2:1: +2:2 return; // scope 0 at $DIR/array_index.rs:+2:2: +2:2 } diff --git a/src/test/mir-opt/const_prop/array_index.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/array_index.main.ConstProp.64bit.diff index bb9abdd1020..439b2a3e16b 100644 --- a/src/test/mir-opt/const_prop/array_index.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/array_index.main.ConstProp.64bit.diff @@ -18,11 +18,12 @@ _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; // scope 0 at $DIR/array_index.rs:+1:18: +1:30 StorageLive(_3); // scope 0 at $DIR/array_index.rs:+1:31: +1:32 _3 = const 2_usize; // scope 0 at $DIR/array_index.rs:+1:31: +1:32 - _4 = const 4_usize; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 +- _4 = Len(_2); // scope 0 at $DIR/array_index.rs:+1:18: +1:33 - _5 = Lt(_3, _4); // scope 0 at $DIR/array_index.rs:+1:18: +1:33 - assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 ++ _4 = const 4_usize; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 + _5 = const true; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 -+ assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 ++ assert(const true, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 } bb1: { @@ -30,7 +31,7 @@ + _1 = const 2_u32; // scope 0 at $DIR/array_index.rs:+1:18: +1:33 StorageDead(_3); // scope 0 at $DIR/array_index.rs:+1:33: +1:34 StorageDead(_2); // scope 0 at $DIR/array_index.rs:+1:33: +1:34 - nop; // scope 0 at $DIR/array_index.rs:+0:11: +2:2 + _0 = const (); // scope 0 at $DIR/array_index.rs:+0:11: +2:2 StorageDead(_1); // scope 0 at $DIR/array_index.rs:+2:1: +2:2 return; // scope 0 at $DIR/array_index.rs:+2:2: +2:2 } diff --git a/src/test/mir-opt/const_prop/array_index.rs b/src/test/mir-opt/const_prop/array_index.rs index 2c5254b5deb..d31c2827b4e 100644 --- a/src/test/mir-opt/const_prop/array_index.rs +++ b/src/test/mir-opt/const_prop/array_index.rs @@ -1,3 +1,4 @@ +// unit-test: ConstProp // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR array_index.main.ConstProp.diff diff --git a/src/test/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff index 45134a3fdff..bea32a67ef4 100644 --- a/src/test/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff @@ -24,10 +24,9 @@ StorageLive(_3); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19 - _3 = _1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19 - _4 = Eq(_3, const 0_i32); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 -- assert(!move _4, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 + _3 = const 0_i32; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19 + _4 = const true; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 -+ assert(!const true, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 + assert(!move _4, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 } bb1: { @@ -38,14 +37,13 @@ + _5 = const false; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 + _6 = const false; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 + _7 = const false; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 -+ assert(!const false, "attempt to compute `{} / {}`, which would overflow", const 1_i32, const 0_i32) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 ++ assert(!const false, "attempt to compute `{} / {}`, which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 } bb2: { -- _2 = Div(const 1_i32, move _3); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 -+ _2 = Div(const 1_i32, const 0_i32); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 + _2 = Div(const 1_i32, move _3); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19 StorageDead(_3); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19 - nop; // scope 0 at $DIR/bad_op_div_by_zero.rs:+0:11: +3:2 + _0 = const (); // scope 0 at $DIR/bad_op_div_by_zero.rs:+0:11: +3:2 StorageDead(_2); // scope 1 at $DIR/bad_op_div_by_zero.rs:+3:1: +3:2 StorageDead(_1); // scope 0 at $DIR/bad_op_div_by_zero.rs:+3:1: +3:2 return; // scope 0 at $DIR/bad_op_div_by_zero.rs:+3:2: +3:2 diff --git a/src/test/mir-opt/const_prop/bad_op_div_by_zero.rs b/src/test/mir-opt/const_prop/bad_op_div_by_zero.rs index 6f39209b970..a6fd325ece0 100644 --- a/src/test/mir-opt/const_prop/bad_op_div_by_zero.rs +++ b/src/test/mir-opt/const_prop/bad_op_div_by_zero.rs @@ -1,3 +1,4 @@ +// unit-test: ConstProp // EMIT_MIR bad_op_div_by_zero.main.ConstProp.diff #[allow(unconditional_panic)] fn main() { diff --git a/src/test/mir-opt/const_prop/boolean_identities.rs b/src/test/mir-opt/const_prop/boolean_identities.rs index 57164e3e794..c7b609949cd 100644 --- a/src/test/mir-opt/const_prop/boolean_identities.rs +++ b/src/test/mir-opt/const_prop/boolean_identities.rs @@ -1,3 +1,4 @@ +// unit-test: ConstProp // compile-flags: -O -Zmir-opt-level=4 // EMIT_MIR boolean_identities.test.ConstProp.diff diff --git a/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff b/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff index f2d4bee1bf9..d6a1485e17c 100644 --- a/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff @@ -26,12 +26,11 @@ StorageLive(_3); // scope 0 at $DIR/boxes.rs:+1:14: +1:22 - _4 = SizeOf(i32); // scope 2 at $DIR/boxes.rs:+1:14: +1:22 - _5 = AlignOf(i32); // scope 2 at $DIR/boxes.rs:+1:14: +1:22 -- _6 = alloc::alloc::exchange_malloc(move _4, move _5) -> bb1; // scope 2 at $DIR/boxes.rs:+1:14: +1:22 + _4 = const 4_usize; // scope 2 at $DIR/boxes.rs:+1:14: +1:22 + _5 = const 4_usize; // scope 2 at $DIR/boxes.rs:+1:14: +1:22 -+ _6 = alloc::alloc::exchange_malloc(const 4_usize, const 4_usize) -> bb1; // scope 2 at $DIR/boxes.rs:+1:14: +1:22 + _6 = alloc::alloc::exchange_malloc(move _4, move _5) -> bb1; // scope 2 at $DIR/boxes.rs:+1:14: +1:22 // mir::Constant - // + span: $DIR/boxes.rs:12:14: 12:22 + // + span: $DIR/boxes.rs:13:14: 13:22 // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value() } } @@ -55,7 +54,7 @@ bb2: { StorageDead(_3); // scope 0 at $DIR/boxes.rs:+1:26: +1:27 - nop; // scope 0 at $DIR/boxes.rs:+0:11: +2:2 + _0 = const (); // scope 0 at $DIR/boxes.rs:+0:11: +2:2 StorageDead(_1); // scope 0 at $DIR/boxes.rs:+2:1: +2:2 return; // scope 0 at $DIR/boxes.rs:+2:2: +2:2 } diff --git a/src/test/mir-opt/const_prop/boxes.rs b/src/test/mir-opt/const_prop/boxes.rs index fea666a4455..d287830db5a 100644 --- a/src/test/mir-opt/const_prop/boxes.rs +++ b/src/test/mir-opt/const_prop/boxes.rs @@ -1,3 +1,4 @@ +// unit-test: ConstProp // compile-flags: -O // ignore-emscripten compiled with panic=abort by default // ignore-wasm32 diff --git a/src/test/mir-opt/const_prop/cast.main.ConstProp.diff b/src/test/mir-opt/const_prop/cast.main.ConstProp.diff index 5698a612fe2..e040a4b3a53 100644 --- a/src/test/mir-opt/const_prop/cast.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/cast.main.ConstProp.diff @@ -19,7 +19,7 @@ StorageLive(_2); // scope 1 at $DIR/cast.rs:+3:9: +3:10 - _2 = const 42_u32 as u8 (Misc); // scope 1 at $DIR/cast.rs:+3:13: +3:24 + _2 = const 42_u8; // scope 1 at $DIR/cast.rs:+3:13: +3:24 - nop; // scope 0 at $DIR/cast.rs:+0:11: +4:2 + _0 = const (); // scope 0 at $DIR/cast.rs:+0:11: +4:2 StorageDead(_2); // scope 1 at $DIR/cast.rs:+4:1: +4:2 StorageDead(_1); // scope 0 at $DIR/cast.rs:+4:1: +4:2 return; // scope 0 at $DIR/cast.rs:+4:2: +4:2 diff --git a/src/test/mir-opt/const_prop/cast.rs b/src/test/mir-opt/const_prop/cast.rs index 680cab00740..984086eda48 100644 --- a/src/test/mir-opt/const_prop/cast.rs +++ b/src/test/mir-opt/const_prop/cast.rs @@ -1,3 +1,4 @@ +// unit-test: ConstProp // EMIT_MIR cast.main.ConstProp.diff fn main() { diff --git a/src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff b/src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff index 5e33d054207..96d0d25664a 100644 --- a/src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff @@ -20,7 +20,7 @@ bb1: { - _1 = move (_2.0: u32); // scope 0 at $DIR/checked_add.rs:+1:18: +1:23 + _1 = const 2_u32; // scope 0 at $DIR/checked_add.rs:+1:18: +1:23 - nop; // scope 0 at $DIR/checked_add.rs:+0:11: +2:2 + _0 = const (); // scope 0 at $DIR/checked_add.rs:+0:11: +2:2 StorageDead(_1); // scope 0 at $DIR/checked_add.rs:+2:1: +2:2 return; // scope 0 at $DIR/checked_add.rs:+2:2: +2:2 } diff --git a/src/test/mir-opt/const_prop/checked_add.rs b/src/test/mir-opt/const_prop/checked_add.rs index 08d59b6fbc3..b9860da4c82 100644 --- a/src/test/mir-opt/const_prop/checked_add.rs +++ b/src/test/mir-opt/const_prop/checked_add.rs @@ -1,3 +1,4 @@ +// unit-test: ConstProp // compile-flags: -C overflow-checks=on // EMIT_MIR checked_add.main.ConstProp.diff diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff index c21b24591d8..2cb071deab1 100644 --- a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff @@ -18,7 +18,7 @@ StorageLive(_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16 _3 = const FOO; // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16 // mir::Constant - // + span: $DIR/const_prop_fails_gracefully.rs:7:13: 7:16 + // + span: $DIR/const_prop_fails_gracefully.rs:8:13: 8:16 // + literal: Const { ty: &i32, val: Unevaluated(FOO, [], None) } _2 = &raw const (*_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16 _1 = move _2 as usize (PointerExposeAddress); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:39 @@ -29,14 +29,14 @@ _5 = _1; // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:10: +3:11 _4 = read(move _5) -> bb1; // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:5: +3:12 // mir::Constant - // + span: $DIR/const_prop_fails_gracefully.rs:8:5: 8:9 + // + span: $DIR/const_prop_fails_gracefully.rs:9:5: 9:9 // + literal: Const { ty: fn(usize) {read}, val: Value() } } bb1: { StorageDead(_5); // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:11: +3:12 StorageDead(_4); // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:12: +3:13 - nop; // scope 0 at $DIR/const_prop_fails_gracefully.rs:+0:11: +4:2 + _0 = const (); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+0:11: +4:2 StorageDead(_1); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+4:1: +4:2 return; // scope 0 at $DIR/const_prop_fails_gracefully.rs:+4:2: +4:2 } diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs index 8bd68527f37..0a3dcbd380f 100644 --- a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs +++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs @@ -1,3 +1,4 @@ +// unit-test: ConstProp #[inline(never)] fn read(_: usize) { } diff --git a/src/test/mir-opt/const_prop/control-flow-simplification.rs b/src/test/mir-opt/const_prop/control-flow-simplification.rs index aa4ce19f620..7dbe8e7344b 100644 --- a/src/test/mir-opt/const_prop/control-flow-simplification.rs +++ b/src/test/mir-opt/const_prop/control-flow-simplification.rs @@ -1,10 +1,11 @@ +// unit-test: ConstProp // compile-flags: -Zmir-opt-level=1 -trait NeedsDrop:Sized{ - const NEEDS:bool=std::mem::needs_drop::(); +trait NeedsDrop: Sized { + const NEEDS: bool = std::mem::needs_drop::(); } -impl NeedsDrop for This{} +impl NeedsDrop for This {} // EMIT_MIR control_flow_simplification.hello.ConstProp.diff // EMIT_MIR control_flow_simplification.hello.PreCodegen.before.mir diff --git a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff index 5b4ecaa80f1..6b29bb59c40 100644 --- a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff @@ -44,7 +44,7 @@ _1 = Add(move _2, const 0_i32); // scope 0 at $DIR/discriminant.rs:+1:13: +1:68 StorageDead(_2); // scope 0 at $DIR/discriminant.rs:+1:67: +1:68 StorageDead(_3); // scope 0 at $DIR/discriminant.rs:+1:68: +1:69 - nop; // scope 0 at $DIR/discriminant.rs:+0:11: +2:2 + _0 = const (); // scope 0 at $DIR/discriminant.rs:+0:11: +2:2 StorageDead(_1); // scope 0 at $DIR/discriminant.rs:+2:1: +2:2 return; // scope 0 at $DIR/discriminant.rs:+2:2: +2:2 } diff --git a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff index 5b4ecaa80f1..6b29bb59c40 100644 --- a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff @@ -44,7 +44,7 @@ _1 = Add(move _2, const 0_i32); // scope 0 at $DIR/discriminant.rs:+1:13: +1:68 StorageDead(_2); // scope 0 at $DIR/discriminant.rs:+1:67: +1:68 StorageDead(_3); // scope 0 at $DIR/discriminant.rs:+1:68: +1:69 - nop; // scope 0 at $DIR/discriminant.rs:+0:11: +2:2 + _0 = const (); // scope 0 at $DIR/discriminant.rs:+0:11: +2:2 StorageDead(_1); // scope 0 at $DIR/discriminant.rs:+2:1: +2:2 return; // scope 0 at $DIR/discriminant.rs:+2:2: +2:2 } diff --git a/src/test/mir-opt/const_prop/discriminant.rs b/src/test/mir-opt/const_prop/discriminant.rs index 67538b3c7a5..fdd67ca8ac4 100644 --- a/src/test/mir-opt/const_prop/discriminant.rs +++ b/src/test/mir-opt/const_prop/discriminant.rs @@ -1,3 +1,4 @@ +// unit-test: ConstProp // compile-flags: -O // FIXME(wesleywiser): Ideally, we could const-prop away all of this and just be left with diff --git a/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff b/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff index 2e1e32545a2..948bb7f56fe 100644 --- a/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff @@ -18,14 +18,14 @@ - assert(!move (_3.1: bool), "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:+1:13: +1:29 + _2 = const 2_u8; // scope 0 at $DIR/indirect.rs:+1:13: +1:25 + _3 = const (3_u8, false); // scope 0 at $DIR/indirect.rs:+1:13: +1:29 -+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u8, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:+1:13: +1:29 ++ assert(!const false, "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:+1:13: +1:29 } bb1: { - _1 = move (_3.0: u8); // scope 0 at $DIR/indirect.rs:+1:13: +1:29 + _1 = const 3_u8; // scope 0 at $DIR/indirect.rs:+1:13: +1:29 StorageDead(_2); // scope 0 at $DIR/indirect.rs:+1:28: +1:29 - nop; // scope 0 at $DIR/indirect.rs:+0:11: +2:2 + _0 = const (); // scope 0 at $DIR/indirect.rs:+0:11: +2:2 StorageDead(_1); // scope 0 at $DIR/indirect.rs:+2:1: +2:2 return; // scope 0 at $DIR/indirect.rs:+2:2: +2:2 } diff --git a/src/test/mir-opt/const_prop/indirect.rs b/src/test/mir-opt/const_prop/indirect.rs index 37217ca8134..44916cbfe74 100644 --- a/src/test/mir-opt/const_prop/indirect.rs +++ b/src/test/mir-opt/const_prop/indirect.rs @@ -1,3 +1,4 @@ +// unit-test: ConstProp // compile-flags: -C overflow-checks=on // EMIT_MIR indirect.main.ConstProp.diff diff --git a/src/test/mir-opt/const_prop/issue-66971.rs b/src/test/mir-opt/const_prop/issue-66971.rs index 81eccae46b9..6ca03438ef3 100644 --- a/src/test/mir-opt/const_prop/issue-66971.rs +++ b/src/test/mir-opt/const_prop/issue-66971.rs @@ -1,3 +1,4 @@ +// unit-test: ConstProp // compile-flags: -Z mir-opt-level=3 // Due to a bug in propagating scalar pairs the assertion below used to fail. In the expected diff --git a/src/test/mir-opt/const_prop/issue-67019.rs b/src/test/mir-opt/const_prop/issue-67019.rs index c78b8b97178..ffc6fa1f290 100644 --- a/src/test/mir-opt/const_prop/issue-67019.rs +++ b/src/test/mir-opt/const_prop/issue-67019.rs @@ -1,3 +1,4 @@ +// unit-test: ConstProp // compile-flags: -Z mir-opt-level=3 // This used to ICE in const-prop diff --git a/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff b/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff index b3d5980aa73..9d541dcabbb 100644 --- a/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff @@ -19,7 +19,7 @@ StorageDead(_3); // scope 0 at $DIR/issue-66971.rs:+1:21: +1:22 _1 = encode(move _2) -> bb1; // scope 0 at $DIR/issue-66971.rs:+1:5: +1:23 // mir::Constant - // + span: $DIR/issue-66971.rs:16:5: 16:11 + // + span: $DIR/issue-66971.rs:17:5: 17:11 // + literal: Const { ty: fn(((), u8, u8)) {encode}, val: Value() } } diff --git a/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff b/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff index 8330b50529f..b79d814760d 100644 --- a/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff @@ -20,7 +20,7 @@ StorageDead(_3); // scope 0 at $DIR/issue-67019.rs:+1:18: +1:19 _1 = test(move _2) -> bb1; // scope 0 at $DIR/issue-67019.rs:+1:5: +1:20 // mir::Constant - // + span: $DIR/issue-67019.rs:11:5: 11:9 + // + span: $DIR/issue-67019.rs:12:5: 12:9 // + literal: Const { ty: fn(((u8, u8),)) {test}, val: Value() } } diff --git a/src/test/mir-opt/const_prop/mult_by_zero.rs b/src/test/mir-opt/const_prop/mult_by_zero.rs index b0ecdf1818e..c839f92f2ce 100644 --- a/src/test/mir-opt/const_prop/mult_by_zero.rs +++ b/src/test/mir-opt/const_prop/mult_by_zero.rs @@ -1,3 +1,4 @@ +// unit-test // compile-flags: -O -Zmir-opt-level=4 // EMIT_MIR mult_by_zero.test.ConstProp.diff diff --git a/src/test/mir-opt/const_prop/mutable_variable.rs b/src/test/mir-opt/const_prop/mutable_variable.rs index 801e7a9fcbb..cb01719dd77 100644 --- a/src/test/mir-opt/const_prop/mutable_variable.rs +++ b/src/test/mir-opt/const_prop/mutable_variable.rs @@ -1,3 +1,4 @@ +// unit-test // compile-flags: -O // EMIT_MIR mutable_variable.main.ConstProp.diff diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate.rs b/src/test/mir-opt/const_prop/mutable_variable_aggregate.rs index e0b4b77bac4..d4ff8d89073 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_aggregate.rs +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate.rs @@ -1,3 +1,4 @@ +// unit-test // compile-flags: -O // EMIT_MIR mutable_variable_aggregate.main.ConstProp.diff diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs index 79ac497c783..9060f7e9bd3 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs @@ -1,3 +1,4 @@ +// unit-test // compile-flags: -O // EMIT_MIR mutable_variable_aggregate_mut_ref.main.ConstProp.diff diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff index c678f7b0327..6eda503c1ee 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff @@ -16,7 +16,7 @@ StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:9: +1:14 _1 = foo() -> bb1; // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:29: +1:34 // mir::Constant - // + span: $DIR/mutable_variable_aggregate_partial_read.rs:5:29: 5:32 + // + span: $DIR/mutable_variable_aggregate_partial_read.rs:6:29: 6:32 // + literal: Const { ty: fn() -> (i32, i32) {foo}, val: Value() } } diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs index 9bb62b8973c..cb59509ff10 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs @@ -1,3 +1,4 @@ +// unit-test // compile-flags: -O // EMIT_MIR mutable_variable_aggregate_partial_read.main.ConstProp.diff diff --git a/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff index 4c2ba9a0998..eb3a7bc96d8 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff @@ -25,7 +25,7 @@ StorageLive(_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 _4 = const {alloc1: *mut u32}; // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 // mir::Constant - // + span: $DIR/mutable_variable_no_prop.rs:9:13: 9:19 + // + span: $DIR/mutable_variable_no_prop.rs:10:13: 10:19 // + literal: Const { ty: *mut u32, val: Value(Scalar(alloc1)) } _3 = (*_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 _1 = move _3; // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:9: +3:19 diff --git a/src/test/mir-opt/const_prop/mutable_variable_no_prop.rs b/src/test/mir-opt/const_prop/mutable_variable_no_prop.rs index 4126fb3c68c..8c23c5fcf0f 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_no_prop.rs +++ b/src/test/mir-opt/const_prop/mutable_variable_no_prop.rs @@ -1,3 +1,4 @@ +// unit-test // compile-flags: -O static mut STATIC: u32 = 42; diff --git a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff index 5328792b323..4f205667be0 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff @@ -25,7 +25,7 @@ StorageLive(_1); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10 _1 = foo() -> bb1; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:13: +1:18 // mir::Constant - // + span: $DIR/mutable_variable_unprop_assign.rs:5:13: 5:16 + // + span: $DIR/mutable_variable_unprop_assign.rs:6:13: 6:16 // + literal: Const { ty: fn() -> i32 {foo}, val: Value() } } diff --git a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.rs b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.rs index 13f1b3f47f2..b077cfd3e0a 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.rs +++ b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.rs @@ -1,3 +1,4 @@ +// unit-test // compile-flags: -O // EMIT_MIR mutable_variable_unprop_assign.main.ConstProp.diff diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.rs b/src/test/mir-opt/const_prop/optimizes_into_variable.rs index 17265b7eb85..c0fbd2558cd 100644 --- a/src/test/mir-opt/const_prop/optimizes_into_variable.rs +++ b/src/test/mir-opt/const_prop/optimizes_into_variable.rs @@ -1,3 +1,4 @@ +// unit-test // compile-flags: -C overflow-checks=on struct Point { diff --git a/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff b/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff index 89f43d75138..b9c283a5482 100644 --- a/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff @@ -18,7 +18,7 @@ StorageLive(_3); // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 _3 = const {alloc1: &u8}; // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 // mir::Constant - // + span: $DIR/read_immutable_static.rs:7:13: 7:16 + // + span: $DIR/read_immutable_static.rs:8:13: 8:16 // + literal: Const { ty: &u8, val: Value(Scalar(alloc1)) } - _2 = (*_3); // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 + _2 = const 2_u8; // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16 @@ -26,7 +26,7 @@ StorageLive(_5); // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 _5 = const {alloc1: &u8}; // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 // mir::Constant - // + span: $DIR/read_immutable_static.rs:7:19: 7:22 + // + span: $DIR/read_immutable_static.rs:8:19: 8:22 // + literal: Const { ty: &u8, val: Value(Scalar(alloc1)) } - _4 = (*_5); // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22 - _1 = Add(move _2, move _4); // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:22 diff --git a/src/test/mir-opt/const_prop/read_immutable_static.rs b/src/test/mir-opt/const_prop/read_immutable_static.rs index 8a5f12c6f3d..4f7afe6cad4 100644 --- a/src/test/mir-opt/const_prop/read_immutable_static.rs +++ b/src/test/mir-opt/const_prop/read_immutable_static.rs @@ -1,3 +1,4 @@ +// unit-test // compile-flags: -O static FOO: u8 = 2; diff --git a/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff b/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff index f0c89caeac6..84ec5c8bb1d 100644 --- a/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff @@ -13,7 +13,7 @@ StorageLive(_2); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 // mir::Constant - // + span: $DIR/ref_deref_project.rs:5:6: 5:17 + // + span: $DIR/ref_deref_project.rs:6:6: 6:17 // + literal: Const { ty: &(i32, i32), val: Unevaluated(main, [], Some(promoted[0])) } _2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 _1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17 diff --git a/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff b/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff index d2554028792..6f3a060a126 100644 --- a/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff +++ b/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff @@ -16,7 +16,7 @@ - _2 = &(_3.1: i32); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 + _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 + // mir::Constant -+ // + span: $DIR/ref_deref_project.rs:5:6: 5:17 ++ // + span: $DIR/ref_deref_project.rs:6:6: 6:17 + // + literal: Const { ty: &(i32, i32), val: Unevaluated(main, [], Some(promoted[0])) } + _2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17 _1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17 diff --git a/src/test/mir-opt/const_prop/ref_deref_project.rs b/src/test/mir-opt/const_prop/ref_deref_project.rs index c7cc73651f6..659c11d9b0c 100644 --- a/src/test/mir-opt/const_prop/ref_deref_project.rs +++ b/src/test/mir-opt/const_prop/ref_deref_project.rs @@ -1,3 +1,4 @@ +// unit-test // EMIT_MIR ref_deref_project.main.PromoteTemps.diff // EMIT_MIR ref_deref_project.main.ConstProp.diff -- cgit 1.4.1-3-g733a5 From aca05cf6038278d7774311720534437f0ec42bc2 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Fri, 12 Aug 2022 12:48:40 +0200 Subject: Fix alignment flag for emit_small_memory_copy Do not unconditionally pass the "aligned" MemFlag when calling emit_small_memory_copy. Instead, allow the back end to rely on the alignment info passed separately to this routine. --- src/value_and_place.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/value_and_place.rs b/src/value_and_place.rs index e48d095d139..9e945d83621 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -614,7 +614,7 @@ impl<'tcx> CPlace<'tcx> { dst_align, src_align, true, - MemFlags::trusted(), + flags, ); } CValueInner::ByRef(_, Some(_)) => todo!(), -- cgit 1.4.1-3-g733a5 From 48b312f04a89c72cf6db2cbb08bbc7fe6fce9bdb Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 12 Aug 2022 09:55:59 +0000 Subject: Don't take TyCtxt as argument for compile_global_asm This allows it to be executed on a background thread. --- src/driver/aot.rs | 21 ++++++++++++--- src/global_asm.rs | 77 +++++++++++++++++++++++++++++++------------------------ 2 files changed, 61 insertions(+), 37 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 0816ebc4599..0ca634affb4 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -1,6 +1,8 @@ //! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a //! standalone executable. +use std::sync::Arc; + use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file; use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -14,6 +16,7 @@ use rustc_session::Session; use cranelift_codegen::isa::TargetIsa; use cranelift_object::{ObjectBuilder, ObjectModule}; +use crate::global_asm::GlobalAsmConfig; use crate::{prelude::*, BackendConfig}; struct ModuleCodegenResult(CompiledModule, Option<(WorkProductId, WorkProduct)>); @@ -141,7 +144,11 @@ fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCo fn module_codegen( tcx: TyCtxt<'_>, - (backend_config, cgu_name): (BackendConfig, rustc_span::Symbol), + (backend_config, global_asm_config, cgu_name): ( + BackendConfig, + Arc, + rustc_span::Symbol, + ), ) -> ModuleCodegenResult { let cgu = tcx.codegen_unit(cgu_name); let mono_items = cgu.items_in_deterministic_order(tcx); @@ -198,9 +205,13 @@ fn module_codegen( ) }); - match crate::global_asm::compile_global_asm(tcx, cgu.name().as_str(), &cx.global_asm) { + match crate::global_asm::compile_global_asm( + &global_asm_config, + cgu.name().as_str(), + &cx.global_asm, + ) { Ok(()) => {} - Err(err) => tcx.sess.fatal(&err.to_string()), + Err(err) => tcx.sess.fatal(&err), } codegen_result @@ -226,6 +237,8 @@ pub(crate) fn run_aot( } } + let global_asm_config = Arc::new(crate::global_asm::GlobalAsmConfig::new(tcx)); + let modules = super::time(tcx, backend_config.display_cg_time, "codegen mono items", || { cgus.iter() .map(|cgu| { @@ -243,7 +256,7 @@ pub(crate) fn run_aot( .with_task( dep_node, tcx, - (backend_config.clone(), cgu.name()), + (backend_config.clone(), global_asm_config.clone(), cgu.name()), module_codegen, Some(rustc_middle::dep_graph::hash_result), ) diff --git a/src/global_asm.rs b/src/global_asm.rs index 5cd7abfdfb5..14288e99242 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -1,13 +1,14 @@ //! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a //! standalone executable. -use std::io::{self, Write}; +use std::io::Write; use std::path::PathBuf; use std::process::{Command, Stdio}; +use std::sync::Arc; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::ItemId; -use rustc_session::config::OutputType; +use rustc_session::config::{OutputFilenames, OutputType}; use crate::prelude::*; @@ -31,40 +32,56 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, } } +#[derive(Debug)] +pub(crate) struct GlobalAsmConfig { + asm_enabled: bool, + assembler: PathBuf, + linker: PathBuf, + output_filenames: Arc, +} + +impl GlobalAsmConfig { + pub(crate) fn new(tcx: TyCtxt<'_>) -> Self { + let asm_enabled = cfg!(feature = "inline_asm") + && !tcx.sess.target.is_like_osx + && !tcx.sess.target.is_like_windows; + + GlobalAsmConfig { + asm_enabled, + assembler: crate::toolchain::get_toolchain_binary(tcx.sess, "as"), + linker: crate::toolchain::get_toolchain_binary(tcx.sess, "ld"), + output_filenames: tcx.output_filenames(()).clone(), + } + } +} + pub(crate) fn compile_global_asm( - tcx: TyCtxt<'_>, + config: &GlobalAsmConfig, cgu_name: &str, global_asm: &str, -) -> io::Result<()> { +) -> Result<(), String> { if global_asm.is_empty() { return Ok(()); } - if cfg!(not(feature = "inline_asm")) - || tcx.sess.target.is_like_osx - || tcx.sess.target.is_like_windows - { + if !config.asm_enabled { if global_asm.contains("__rust_probestack") { return Ok(()); } // FIXME fix linker error on macOS if cfg!(not(feature = "inline_asm")) { - return Err(io::Error::new( - io::ErrorKind::Unsupported, - "asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift", - )); + return Err( + "asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift" + .to_owned(), + ); } else { - return Err(io::Error::new( - io::ErrorKind::Unsupported, - "asm! and global_asm! are not yet supported on macOS and Windows", - )); + return Err( + "asm! and global_asm! are not yet supported on macOS and Windows".to_owned() + ); } } - let assembler = crate::toolchain::get_toolchain_binary(tcx.sess, "as"); - let linker = crate::toolchain::get_toolchain_binary(tcx.sess, "ld"); - // Remove all LLVM style comments let global_asm = global_asm .lines() @@ -72,11 +89,11 @@ pub(crate) fn compile_global_asm( .collect::>() .join("\n"); - let output_object_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu_name)); + let output_object_file = config.output_filenames.temp_path(OutputType::Object, Some(cgu_name)); // Assemble `global_asm` let global_asm_object_file = add_file_stem_postfix(output_object_file.clone(), ".asm"); - let mut child = Command::new(assembler) + let mut child = Command::new(&config.assembler) .arg("-o") .arg(&global_asm_object_file) .stdin(Stdio::piped()) @@ -85,16 +102,13 @@ pub(crate) fn compile_global_asm( child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap(); let status = child.wait().expect("Failed to wait for `as`."); if !status.success() { - return Err(io::Error::new( - io::ErrorKind::Other, - format!("Failed to assemble `{}`", global_asm), - )); + return Err(format!("Failed to assemble `{}`", global_asm)); } // Link the global asm and main object file together let main_object_file = add_file_stem_postfix(output_object_file.clone(), ".main"); std::fs::rename(&output_object_file, &main_object_file).unwrap(); - let status = Command::new(linker) + let status = Command::new(&config.linker) .arg("-r") // Create a new object file .arg("-o") .arg(output_object_file) @@ -103,13 +117,10 @@ pub(crate) fn compile_global_asm( .status() .unwrap(); if !status.success() { - return Err(io::Error::new( - io::ErrorKind::Other, - format!( - "Failed to link `{}` and `{}` together", - main_object_file.display(), - global_asm_object_file.display(), - ), + return Err(format!( + "Failed to link `{}` and `{}` together", + main_object_file.display(), + global_asm_object_file.display(), )); } -- cgit 1.4.1-3-g733a5 From 8bcab190183f2a1807ff3d10fcdf7ea74306cf2f Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Fri, 12 Aug 2022 13:46:31 +0200 Subject: Ignore ptr_bitops_tagging test on s390x This test requires dynamic stack re-alignment on s390x, which is currently unsupported (see issue #1258). --- patches/0023-sysroot-Ignore-failing-tests.patch | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/patches/0023-sysroot-Ignore-failing-tests.patch b/patches/0023-sysroot-Ignore-failing-tests.patch index 50ef0bd9418..f3cd7ee77e2 100644 --- a/patches/0023-sysroot-Ignore-failing-tests.patch +++ b/patches/0023-sysroot-Ignore-failing-tests.patch @@ -46,5 +46,17 @@ index 4bc44e9..8e3c7a4 100644 #[test] fn cell_allows_array_cycle() { +diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs +index 13b12db..96fe4b9 100644 +--- a/library/core/tests/atomic.rs ++++ b/library/core/tests/atomic.rs +@@ -185,6 +185,7 @@ fn ptr_bitops() { + } + + #[test] ++#[cfg_attr(target_arch = "s390x", ignore)] // s390x backend doesn't support stack alignment >8 bytes + #[cfg(any(not(target_arch = "arm"), target_os = "linux"))] // Missing intrinsic in compiler-builtins + fn ptr_bitops_tagging() { + #[repr(align(16))] -- 2.21.0 (Apple Git-122) -- cgit 1.4.1-3-g733a5 From e45f6000a0bd46d4b7580db59c86f3d30adbc270 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 12 Aug 2022 12:27:47 +0000 Subject: Remove the partial linking hack for global asm support --- src/driver/aot.rs | 102 +++++++++++++++++++++++++++++++++++++++++++----------- src/global_asm.rs | 34 +++--------------- 2 files changed, 87 insertions(+), 49 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 0ca634affb4..4122ce18224 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -1,6 +1,7 @@ //! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a //! standalone executable. +use std::path::PathBuf; use std::sync::Arc; use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file; @@ -19,7 +20,11 @@ use cranelift_object::{ObjectBuilder, ObjectModule}; use crate::global_asm::GlobalAsmConfig; use crate::{prelude::*, BackendConfig}; -struct ModuleCodegenResult(CompiledModule, Option<(WorkProductId, WorkProduct)>); +struct ModuleCodegenResult( + CompiledModule, + Option, + Option<(WorkProductId, WorkProduct)>, +); impl HashStable for ModuleCodegenResult { fn hash_stable(&self, _: &mut HCX, _: &mut StableHasher) { @@ -42,11 +47,15 @@ impl OngoingCodegen { let mut modules = vec![]; for module_codegen_result in self.modules { - let ModuleCodegenResult(module, work_product) = module_codegen_result; + let ModuleCodegenResult(module_regular, module_global_asm, work_product) = + module_codegen_result; if let Some((work_product_id, work_product)) = work_product { work_products.insert(work_product_id, work_product); } - modules.push(module); + modules.push(module_regular); + if let Some(module_global_asm) = module_global_asm { + modules.push(module_global_asm); + } } ( @@ -80,6 +89,7 @@ fn emit_module( module: ObjectModule, debug: Option>, unwind_context: UnwindContext, + global_asm_object_file: Option, ) -> ModuleCodegenResult { let mut product = module.finish(); @@ -100,6 +110,12 @@ fn emit_module( let work_product = if backend_config.disable_incr_cache { None + } else if let Some(global_asm_object_file) = &global_asm_object_file { + rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( + tcx.sess, + &name, + &[("o", &tmp_file), ("asm.o", global_asm_object_file)], + ) } else { rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( tcx.sess, @@ -109,35 +125,78 @@ fn emit_module( }; ModuleCodegenResult( - CompiledModule { name, kind, object: Some(tmp_file), dwarf_object: None, bytecode: None }, + CompiledModule { + name: name.clone(), + kind, + object: Some(tmp_file), + dwarf_object: None, + bytecode: None, + }, + global_asm_object_file.map(|global_asm_object_file| CompiledModule { + name: format!("{name}.asm"), + kind, + object: Some(global_asm_object_file), + dwarf_object: None, + bytecode: None, + }), work_product, ) } fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCodegenResult { let work_product = cgu.previous_work_product(tcx); - let obj_out = tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str())); - let source_file = rustc_incremental::in_incr_comp_dir_sess( + let obj_out_regular = + tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str())); + let source_file_regular = rustc_incremental::in_incr_comp_dir_sess( &tcx.sess, &work_product.saved_files.get("o").expect("no saved object file in work product"), ); - if let Err(err) = rustc_fs_util::link_or_copy(&source_file, &obj_out) { + + if let Err(err) = rustc_fs_util::link_or_copy(&source_file_regular, &obj_out_regular) { tcx.sess.err(&format!( "unable to copy {} to {}: {}", - source_file.display(), - obj_out.display(), + source_file_regular.display(), + obj_out_regular.display(), err )); } + let obj_out_global_asm = + crate::global_asm::add_file_stem_postfix(obj_out_regular.clone(), ".asm"); + let has_global_asm = if let Some(asm_o) = work_product.saved_files.get("asm.o") { + let source_file_global_asm = rustc_incremental::in_incr_comp_dir_sess(&tcx.sess, asm_o); + if let Err(err) = rustc_fs_util::link_or_copy(&source_file_global_asm, &obj_out_global_asm) + { + tcx.sess.err(&format!( + "unable to copy {} to {}: {}", + source_file_regular.display(), + obj_out_regular.display(), + err + )); + } + true + } else { + false + }; ModuleCodegenResult( CompiledModule { name: cgu.name().to_string(), kind: ModuleKind::Regular, - object: Some(obj_out), + object: Some(obj_out_regular), dwarf_object: None, bytecode: None, }, + if has_global_asm { + Some(CompiledModule { + name: cgu.name().to_string(), + kind: ModuleKind::Regular, + object: Some(obj_out_global_asm), + dwarf_object: None, + bytecode: None, + }) + } else { + None + }, Some((cgu.work_product_id(), work_product)), ) } @@ -191,6 +250,15 @@ fn module_codegen( cgu.is_primary(), ); + let global_asm_object_file = match crate::global_asm::compile_global_asm( + &global_asm_config, + cgu.name().as_str(), + &cx.global_asm, + ) { + Ok(global_asm_object_file) => global_asm_object_file, + Err(err) => tcx.sess.fatal(&err), + }; + let debug_context = cx.debug_context; let unwind_context = cx.unwind_context; let codegen_result = tcx.sess.time("write object file", || { @@ -202,18 +270,10 @@ fn module_codegen( module, debug_context, unwind_context, + global_asm_object_file, ) }); - match crate::global_asm::compile_global_asm( - &global_asm_config, - cgu.name().as_str(), - &cx.global_asm, - ) { - Ok(()) => {} - Err(err) => tcx.sess.fatal(&err), - } - codegen_result } @@ -281,7 +341,7 @@ pub(crate) fn run_aot( crate::allocator::codegen(tcx, &mut allocator_module, &mut allocator_unwind_context); let allocator_module = if created_alloc_shim { - let ModuleCodegenResult(module, work_product) = emit_module( + let ModuleCodegenResult(module, module_global_asm, work_product) = emit_module( tcx, &backend_config, "allocator_shim".to_string(), @@ -289,7 +349,9 @@ pub(crate) fn run_aot( allocator_module, None, allocator_unwind_context, + None, ); + assert!(module_global_asm.is_none()); if let Some((id, product)) = work_product { work_products.insert(id, product); } diff --git a/src/global_asm.rs b/src/global_asm.rs index 14288e99242..8e711988f81 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -36,7 +36,6 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, pub(crate) struct GlobalAsmConfig { asm_enabled: bool, assembler: PathBuf, - linker: PathBuf, output_filenames: Arc, } @@ -49,7 +48,6 @@ impl GlobalAsmConfig { GlobalAsmConfig { asm_enabled, assembler: crate::toolchain::get_toolchain_binary(tcx.sess, "as"), - linker: crate::toolchain::get_toolchain_binary(tcx.sess, "ld"), output_filenames: tcx.output_filenames(()).clone(), } } @@ -59,14 +57,14 @@ pub(crate) fn compile_global_asm( config: &GlobalAsmConfig, cgu_name: &str, global_asm: &str, -) -> Result<(), String> { +) -> Result, String> { if global_asm.is_empty() { - return Ok(()); + return Ok(None); } if !config.asm_enabled { if global_asm.contains("__rust_probestack") { - return Ok(()); + return Ok(None); } // FIXME fix linker error on macOS @@ -105,32 +103,10 @@ pub(crate) fn compile_global_asm( return Err(format!("Failed to assemble `{}`", global_asm)); } - // Link the global asm and main object file together - let main_object_file = add_file_stem_postfix(output_object_file.clone(), ".main"); - std::fs::rename(&output_object_file, &main_object_file).unwrap(); - let status = Command::new(&config.linker) - .arg("-r") // Create a new object file - .arg("-o") - .arg(output_object_file) - .arg(&main_object_file) - .arg(&global_asm_object_file) - .status() - .unwrap(); - if !status.success() { - return Err(format!( - "Failed to link `{}` and `{}` together", - main_object_file.display(), - global_asm_object_file.display(), - )); - } - - std::fs::remove_file(global_asm_object_file).unwrap(); - std::fs::remove_file(main_object_file).unwrap(); - - Ok(()) + Ok(Some(global_asm_object_file)) } -fn add_file_stem_postfix(mut path: PathBuf, postfix: &str) -> PathBuf { +pub(crate) fn add_file_stem_postfix(mut path: PathBuf, postfix: &str) -> PathBuf { let mut new_filename = path.file_stem().unwrap().to_owned(); new_filename.push(postfix); if let Some(extension) = path.extension() { -- cgit 1.4.1-3-g733a5 From f76ca2247998bff4e10b73fcb464a0a83edbfeb0 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 12 Aug 2022 12:30:24 +0000 Subject: Enable inline asm on macOS --- Readme.md | 4 +--- example/mini_core_hello_world.rs | 14 ++++++++++++-- src/global_asm.rs | 8 ++------ 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/Readme.md b/Readme.md index 8a2db5a43ec..1e84c7fa365 100644 --- a/Readme.md +++ b/Readme.md @@ -52,9 +52,7 @@ configuration options. ## Not yet supported * Inline assembly ([no cranelift support](https://github.com/bytecodealliance/wasmtime/issues/1041)) - * On Linux there is support for invoking an external assembler for `global_asm!` and `asm!`. - `llvm_asm!` will remain unimplemented forever. `asm!` doesn't yet support reg classes. You - have to specify specific registers instead. + * On UNIX there is support for invoking an external assembler for `global_asm!` and `asm!`. * SIMD ([tracked here](https://github.com/bjorn3/rustc_codegen_cranelift/issues/171), some basic things work) ## License diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 7e9cbe1bba5..e83be3a3df5 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -321,7 +321,7 @@ fn main() { #[cfg(not(any(jit, windows)))] test_tls(); - #[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))] + #[cfg(all(not(jit), target_arch = "x86_64", any(target_os = "linux", target_os = "darwin")))] unsafe { global_asm_test(); } @@ -343,7 +343,7 @@ fn main() { } } -#[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))] +#[cfg(all(not(jit), target_arch = "x86_64", any(target_os = "linux", target_os = "darwin")))] extern "C" { fn global_asm_test(); } @@ -358,6 +358,16 @@ global_asm! { " } +#[cfg(all(not(jit), target_arch = "x86_64", target_os = "darwin"))] +global_asm! { + " + .global _global_asm_test + _global_asm_test: + // comment that would normally be removed by LLVM + ret + " +} + #[repr(C)] enum c_void { _1, diff --git a/src/global_asm.rs b/src/global_asm.rs index 8e711988f81..917a6fff727 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -41,9 +41,7 @@ pub(crate) struct GlobalAsmConfig { impl GlobalAsmConfig { pub(crate) fn new(tcx: TyCtxt<'_>) -> Self { - let asm_enabled = cfg!(feature = "inline_asm") - && !tcx.sess.target.is_like_osx - && !tcx.sess.target.is_like_windows; + let asm_enabled = cfg!(feature = "inline_asm") && !tcx.sess.target.is_like_windows; GlobalAsmConfig { asm_enabled, @@ -74,9 +72,7 @@ pub(crate) fn compile_global_asm( .to_owned(), ); } else { - return Err( - "asm! and global_asm! are not yet supported on macOS and Windows".to_owned() - ); + return Err("asm! and global_asm! are not yet supported on Windows".to_owned()); } } -- cgit 1.4.1-3-g733a5 From db7d8a811d646cc9f30eb550d2aed7ff3530bb40 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 12 Aug 2022 13:03:18 +0000 Subject: Give fields of ModuleCodegenResult names --- src/driver/aot.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 4122ce18224..3bbd286b3d7 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -20,11 +20,11 @@ use cranelift_object::{ObjectBuilder, ObjectModule}; use crate::global_asm::GlobalAsmConfig; use crate::{prelude::*, BackendConfig}; -struct ModuleCodegenResult( - CompiledModule, - Option, - Option<(WorkProductId, WorkProduct)>, -); +struct ModuleCodegenResult { + module_regular: CompiledModule, + module_global_asm: Option, + work_product: Option<(WorkProductId, WorkProduct)>, +} impl HashStable for ModuleCodegenResult { fn hash_stable(&self, _: &mut HCX, _: &mut StableHasher) { @@ -47,7 +47,7 @@ impl OngoingCodegen { let mut modules = vec![]; for module_codegen_result in self.modules { - let ModuleCodegenResult(module_regular, module_global_asm, work_product) = + let ModuleCodegenResult { module_regular, module_global_asm, work_product } = module_codegen_result; if let Some((work_product_id, work_product)) = work_product { work_products.insert(work_product_id, work_product); @@ -124,15 +124,15 @@ fn emit_module( ) }; - ModuleCodegenResult( - CompiledModule { + ModuleCodegenResult { + module_regular: CompiledModule { name: name.clone(), kind, object: Some(tmp_file), dwarf_object: None, bytecode: None, }, - global_asm_object_file.map(|global_asm_object_file| CompiledModule { + module_global_asm: global_asm_object_file.map(|global_asm_object_file| CompiledModule { name: format!("{name}.asm"), kind, object: Some(global_asm_object_file), @@ -140,7 +140,7 @@ fn emit_module( bytecode: None, }), work_product, - ) + } } fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCodegenResult { @@ -178,15 +178,15 @@ fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCo false }; - ModuleCodegenResult( - CompiledModule { + ModuleCodegenResult { + module_regular: CompiledModule { name: cgu.name().to_string(), kind: ModuleKind::Regular, object: Some(obj_out_regular), dwarf_object: None, bytecode: None, }, - if has_global_asm { + module_global_asm: if has_global_asm { Some(CompiledModule { name: cgu.name().to_string(), kind: ModuleKind::Regular, @@ -197,8 +197,8 @@ fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCo } else { None }, - Some((cgu.work_product_id(), work_product)), - ) + work_product: Some((cgu.work_product_id(), work_product)), + } } fn module_codegen( @@ -341,7 +341,7 @@ pub(crate) fn run_aot( crate::allocator::codegen(tcx, &mut allocator_module, &mut allocator_unwind_context); let allocator_module = if created_alloc_shim { - let ModuleCodegenResult(module, module_global_asm, work_product) = emit_module( + let ModuleCodegenResult { module_regular, module_global_asm, work_product } = emit_module( tcx, &backend_config, "allocator_shim".to_string(), @@ -355,7 +355,7 @@ pub(crate) fn run_aot( if let Some((id, product)) = work_product { work_products.insert(id, product); } - Some(module) + Some(module_regular) } else { None }; -- cgit 1.4.1-3-g733a5 From d3512b1d8e04ab8ab78ea5111a177605d13dfff1 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 12 Aug 2022 13:15:51 +0000 Subject: Don't attempt to do incr comp for the allocator shim The allocator shim doesn't get reused and the allocator shim is just under 2kb, so reusing it is likely more expensive than regenerating it. --- src/driver/aot.rs | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 3bbd286b3d7..ee89d0701aa 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -38,12 +38,11 @@ pub(crate) struct OngoingCodegen { metadata_module: Option, metadata: EncodedMetadata, crate_info: CrateInfo, - work_products: FxHashMap, } impl OngoingCodegen { pub(crate) fn join(self) -> (CodegenResults, FxHashMap) { - let mut work_products = self.work_products; + let mut work_products = FxHashMap::default(); let mut modules = vec![]; for module_codegen_result in self.modules { @@ -331,8 +330,6 @@ pub(crate) fn run_aot( tcx.sess.abort_if_errors(); - let mut work_products = FxHashMap::default(); - let isa = crate::build_isa(tcx.sess, &backend_config); let mut allocator_module = make_module(tcx.sess, isa, "allocator_shim".to_string()); assert_eq!(pointer_ty(tcx), allocator_module.target_config().pointer_type()); @@ -341,21 +338,27 @@ pub(crate) fn run_aot( crate::allocator::codegen(tcx, &mut allocator_module, &mut allocator_unwind_context); let allocator_module = if created_alloc_shim { - let ModuleCodegenResult { module_regular, module_global_asm, work_product } = emit_module( - tcx, - &backend_config, - "allocator_shim".to_string(), - ModuleKind::Allocator, - allocator_module, - None, - allocator_unwind_context, - None, - ); - assert!(module_global_asm.is_none()); - if let Some((id, product)) = work_product { - work_products.insert(id, product); + let name = "allocator_shim".to_owned(); + + let mut product = allocator_module.finish(); + allocator_unwind_context.emit(&mut product); + + let tmp_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(&name)); + let obj = product.object.write().unwrap(); + + tcx.sess.prof.artifact_size("object_file", &*name, obj.len().try_into().unwrap()); + + if let Err(err) = std::fs::write(&tmp_file, obj) { + tcx.sess.fatal(&format!("error writing object file: {}", err)); } - Some(module_regular) + + Some(CompiledModule { + name, + kind: ModuleKind::Allocator, + object: Some(tmp_file), + dwarf_object: None, + bytecode: None, + }) } else { None }; @@ -408,7 +411,6 @@ pub(crate) fn run_aot( metadata_module, metadata, crate_info: CrateInfo::new(tcx, target_cpu), - work_products, }) } -- cgit 1.4.1-3-g733a5 From ab7c706306c65527b5b8b9620e34a65d852cd279 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 12 Aug 2022 18:40:48 +0000 Subject: Move build_isa call into make_module --- src/driver/aot.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index ee89d0701aa..415631ba3e6 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -14,7 +14,6 @@ use rustc_session::cgu_reuse_tracker::CguReuse; use rustc_session::config::{DebugInfo, OutputType}; use rustc_session::Session; -use cranelift_codegen::isa::TargetIsa; use cranelift_object::{ObjectBuilder, ObjectModule}; use crate::global_asm::GlobalAsmConfig; @@ -70,7 +69,9 @@ impl OngoingCodegen { } } -fn make_module(sess: &Session, isa: Box, name: String) -> ObjectModule { +fn make_module(sess: &Session, backend_config: &BackendConfig, name: String) -> ObjectModule { + let isa = crate::build_isa(sess, backend_config); + let mut builder = ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap(); // Unlike cg_llvm, cg_clif defaults to disabling -Zfunction-sections. For cg_llvm binary size @@ -211,8 +212,7 @@ fn module_codegen( let cgu = tcx.codegen_unit(cgu_name); let mono_items = cgu.items_in_deterministic_order(tcx); - let isa = crate::build_isa(tcx.sess, &backend_config); - let mut module = make_module(tcx.sess, isa, cgu_name.as_str().to_string()); + let mut module = make_module(tcx.sess, &backend_config, cgu_name.as_str().to_string()); let mut cx = crate::CodegenCx::new( tcx, @@ -330,9 +330,7 @@ pub(crate) fn run_aot( tcx.sess.abort_if_errors(); - let isa = crate::build_isa(tcx.sess, &backend_config); - let mut allocator_module = make_module(tcx.sess, isa, "allocator_shim".to_string()); - assert_eq!(pointer_ty(tcx), allocator_module.target_config().pointer_type()); + let mut allocator_module = make_module(tcx.sess, &backend_config, "allocator_shim".to_string()); let mut allocator_unwind_context = UnwindContext::new(allocator_module.isa(), true); let created_alloc_shim = crate::allocator::codegen(tcx, &mut allocator_module, &mut allocator_unwind_context); -- cgit 1.4.1-3-g733a5 From 6206c4e927595afcaef0496025512282f847f645 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 12 Aug 2022 18:55:39 +0000 Subject: Stream object file to disk This reduces memory usage and may improve performance slightly. --- src/driver/aot.rs | 70 ++++++++++++++++++++++++------------------------------- 1 file changed, 30 insertions(+), 40 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 415631ba3e6..ff6310bd8af 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -1,6 +1,7 @@ //! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a //! standalone executable. +use std::fs::File; use std::path::PathBuf; use std::sync::Arc; @@ -81,11 +82,10 @@ fn make_module(sess: &Session, backend_config: &BackendConfig, name: String) -> ObjectModule::new(builder) } -fn emit_module( +fn emit_cgu( tcx: TyCtxt<'_>, backend_config: &BackendConfig, name: String, - kind: ModuleKind, module: ObjectModule, debug: Option>, unwind_context: UnwindContext, @@ -99,14 +99,7 @@ fn emit_module( unwind_context.emit(&mut product); - let tmp_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(&name)); - let obj = product.object.write().unwrap(); - - tcx.sess.prof.artifact_size("object_file", name.clone(), obj.len().try_into().unwrap()); - - if let Err(err) = std::fs::write(&tmp_file, obj) { - tcx.sess.fatal(&format!("error writing object file: {}", err)); - } + let module_regular = emit_module(tcx, product.object, ModuleKind::Regular, name.clone()); let work_product = if backend_config.disable_incr_cache { None @@ -114,27 +107,21 @@ fn emit_module( rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( tcx.sess, &name, - &[("o", &tmp_file), ("asm.o", global_asm_object_file)], + &[("o", &module_regular.object.as_ref().unwrap()), ("asm.o", global_asm_object_file)], ) } else { rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( tcx.sess, &name, - &[("o", &tmp_file)], + &[("o", &module_regular.object.as_ref().unwrap())], ) }; ModuleCodegenResult { - module_regular: CompiledModule { - name: name.clone(), - kind, - object: Some(tmp_file), - dwarf_object: None, - bytecode: None, - }, + module_regular, module_global_asm: global_asm_object_file.map(|global_asm_object_file| CompiledModule { name: format!("{name}.asm"), - kind, + kind: ModuleKind::Regular, object: Some(global_asm_object_file), dwarf_object: None, bytecode: None, @@ -143,6 +130,27 @@ fn emit_module( } } +fn emit_module( + tcx: TyCtxt<'_>, + object: cranelift_object::object::write::Object<'_>, + kind: ModuleKind, + name: String, +) -> CompiledModule { + let tmp_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(&name)); + let mut file = match File::create(&tmp_file) { + Ok(file) => file, + Err(err) => tcx.sess.fatal(&format!("error creating object file: {}", err)), + }; + + if let Err(err) = object.write_stream(&mut file) { + tcx.sess.fatal(&format!("error writing object file: {}", err)); + } + + tcx.sess.prof.artifact_size("object_file", &*name, file.metadata().unwrap().len()); + + CompiledModule { name, kind, object: Some(tmp_file), dwarf_object: None, bytecode: None } +} + fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCodegenResult { let work_product = cgu.previous_work_product(tcx); let obj_out_regular = @@ -261,11 +269,10 @@ fn module_codegen( let debug_context = cx.debug_context; let unwind_context = cx.unwind_context; let codegen_result = tcx.sess.time("write object file", || { - emit_module( + emit_cgu( tcx, &backend_config, cgu.name().as_str().to_string(), - ModuleKind::Regular, module, debug_context, unwind_context, @@ -336,27 +343,10 @@ pub(crate) fn run_aot( crate::allocator::codegen(tcx, &mut allocator_module, &mut allocator_unwind_context); let allocator_module = if created_alloc_shim { - let name = "allocator_shim".to_owned(); - let mut product = allocator_module.finish(); allocator_unwind_context.emit(&mut product); - let tmp_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(&name)); - let obj = product.object.write().unwrap(); - - tcx.sess.prof.artifact_size("object_file", &*name, obj.len().try_into().unwrap()); - - if let Err(err) = std::fs::write(&tmp_file, obj) { - tcx.sess.fatal(&format!("error writing object file: {}", err)); - } - - Some(CompiledModule { - name, - kind: ModuleKind::Allocator, - object: Some(tmp_file), - dwarf_object: None, - bytecode: None, - }) + Some(emit_module(tcx, product.object, ModuleKind::Allocator, "allocator_shim".to_owned())) } else { None }; -- cgit 1.4.1-3-g733a5 From c2f0b3a1bf5ed437df3e276960f64bf3c47222e0 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 12 Aug 2022 19:10:16 +0000 Subject: Move copy to incr comp cache to codegen join phase The copy depends on Session, which is only available on the main thread. As such the copy can't be done on future codegen threads. --- src/driver/aot.rs | 58 ++++++++++++++++++++++++++++++++----------------------- src/lib.rs | 30 ++++++++++++++-------------- 2 files changed, 50 insertions(+), 38 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index ff6310bd8af..7e5e3453834 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -23,7 +23,7 @@ use crate::{prelude::*, BackendConfig}; struct ModuleCodegenResult { module_regular: CompiledModule, module_global_asm: Option, - work_product: Option<(WorkProductId, WorkProduct)>, + existing_work_product: Option<(WorkProductId, WorkProduct)>, } impl HashStable for ModuleCodegenResult { @@ -41,16 +41,44 @@ pub(crate) struct OngoingCodegen { } impl OngoingCodegen { - pub(crate) fn join(self) -> (CodegenResults, FxHashMap) { + pub(crate) fn join( + self, + sess: &Session, + backend_config: &BackendConfig, + ) -> (CodegenResults, FxHashMap) { let mut work_products = FxHashMap::default(); let mut modules = vec![]; for module_codegen_result in self.modules { - let ModuleCodegenResult { module_regular, module_global_asm, work_product } = + let ModuleCodegenResult { module_regular, module_global_asm, existing_work_product } = module_codegen_result; - if let Some((work_product_id, work_product)) = work_product { + + if let Some((work_product_id, work_product)) = existing_work_product { work_products.insert(work_product_id, work_product); + } else { + let work_product = if backend_config.disable_incr_cache { + None + } else if let Some(module_global_asm) = &module_global_asm { + rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( + sess, + &module_regular.name, + &[ + ("o", &module_regular.object.as_ref().unwrap()), + ("asm.o", &module_global_asm.object.as_ref().unwrap()), + ], + ) + } else { + rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( + sess, + &module_regular.name, + &[("o", &module_regular.object.as_ref().unwrap())], + ) + }; + if let Some((work_product_id, work_product)) = work_product { + work_products.insert(work_product_id, work_product); + } } + modules.push(module_regular); if let Some(module_global_asm) = module_global_asm { modules.push(module_global_asm); @@ -84,7 +112,6 @@ fn make_module(sess: &Session, backend_config: &BackendConfig, name: String) -> fn emit_cgu( tcx: TyCtxt<'_>, - backend_config: &BackendConfig, name: String, module: ObjectModule, debug: Option>, @@ -101,22 +128,6 @@ fn emit_cgu( let module_regular = emit_module(tcx, product.object, ModuleKind::Regular, name.clone()); - let work_product = if backend_config.disable_incr_cache { - None - } else if let Some(global_asm_object_file) = &global_asm_object_file { - rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( - tcx.sess, - &name, - &[("o", &module_regular.object.as_ref().unwrap()), ("asm.o", global_asm_object_file)], - ) - } else { - rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( - tcx.sess, - &name, - &[("o", &module_regular.object.as_ref().unwrap())], - ) - }; - ModuleCodegenResult { module_regular, module_global_asm: global_asm_object_file.map(|global_asm_object_file| CompiledModule { @@ -126,7 +137,7 @@ fn emit_cgu( dwarf_object: None, bytecode: None, }), - work_product, + existing_work_product: None, } } @@ -205,7 +216,7 @@ fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCo } else { None }, - work_product: Some((cgu.work_product_id(), work_product)), + existing_work_product: Some((cgu.work_product_id(), work_product)), } } @@ -271,7 +282,6 @@ fn module_codegen( let codegen_result = tcx.sess.time("write object file", || { emit_cgu( tcx, - &backend_config, cgu.name().as_str().to_string(), module, debug_context, diff --git a/src/lib.rs b/src/lib.rs index 6ea160d26ce..909f4f00f1e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,7 +25,7 @@ extern crate rustc_target; extern crate rustc_driver; use std::any::Any; -use std::cell::Cell; +use std::cell::{Cell, RefCell}; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::CodegenResults; @@ -158,7 +158,7 @@ impl<'tcx> CodegenCx<'tcx> { } pub struct CraneliftCodegenBackend { - pub config: Option, + pub config: RefCell>, } impl CodegenBackend for CraneliftCodegenBackend { @@ -168,6 +168,13 @@ impl CodegenBackend for CraneliftCodegenBackend { Lto::No | Lto::ThinLocal => {} Lto::Thin | Lto::Fat => sess.warn("LTO is not supported. You may get a linker error."), } + + let mut config = self.config.borrow_mut(); + if config.is_none() { + let new_config = BackendConfig::from_opts(&sess.opts.cg.llvm_args) + .unwrap_or_else(|err| sess.fatal(&err)); + *config = Some(new_config); + } } fn target_features(&self, _sess: &Session, _allow_unstable: bool) -> Vec { @@ -185,15 +192,7 @@ impl CodegenBackend for CraneliftCodegenBackend { need_metadata_module: bool, ) -> Box { tcx.sess.abort_if_errors(); - let config = if let Some(config) = self.config.clone() { - config - } else { - if !tcx.sess.unstable_options() && !tcx.sess.opts.cg.llvm_args.is_empty() { - tcx.sess.fatal("`-Z unstable-options` must be passed to allow configuring cg_clif"); - } - BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args) - .unwrap_or_else(|err| tcx.sess.fatal(&err)) - }; + let config = self.config.borrow().clone().unwrap(); match config.codegen_mode { CodegenMode::Aot => driver::aot::run_aot(tcx, config, metadata, need_metadata_module), CodegenMode::Jit | CodegenMode::JitLazy => { @@ -209,10 +208,13 @@ impl CodegenBackend for CraneliftCodegenBackend { fn join_codegen( &self, ongoing_codegen: Box, - _sess: &Session, + sess: &Session, _outputs: &OutputFilenames, ) -> Result<(CodegenResults, FxHashMap), ErrorGuaranteed> { - Ok(ongoing_codegen.downcast::().unwrap().join()) + Ok(ongoing_codegen + .downcast::() + .unwrap() + .join(sess, self.config.borrow().as_ref().unwrap())) } fn link( @@ -309,5 +311,5 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box Box { - Box::new(CraneliftCodegenBackend { config: None }) + Box::new(CraneliftCodegenBackend { config: RefCell::new(None) }) } -- cgit 1.4.1-3-g733a5 From 0706df5f8cfd5bdd164d10bb67facc2a6c5f6b8f Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Fri, 12 Aug 2022 21:47:36 +0100 Subject: Update abi-checker version --- build_system/abi_checker.rs | 12 ++---------- build_system/prepare.rs | 2 +- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/build_system/abi_checker.rs b/build_system/abi_checker.rs index b6dc0fa6922..67dbd0a38a4 100644 --- a/build_system/abi_checker.rs +++ b/build_system/abi_checker.rs @@ -1,6 +1,6 @@ use super::build_sysroot; use super::config; -use super::utils::spawn_and_wait_with_input; +use super::utils::spawn_and_wait; use build_system::SysrootKind; use std::env; use std::path::Path; @@ -56,13 +56,5 @@ pub(crate) fn run( cmd.arg("--add-rustc-codegen-backend"); cmd.arg(format!("cgclif:{}", cg_clif_dylib_path.display())); - let output = spawn_and_wait_with_input(cmd, "".to_string()); - - // TODO: The correct thing to do here is to check the exit code, but abi-checker - // currently doesn't return 0 on success, so check for the test fail count. - // See: https://github.com/Gankra/abi-checker/issues/10 - let failed = !(output.contains("0 failed") && output.contains("0 completely failed")); - if failed { - panic!("abi-checker failed!"); - } + spawn_and_wait(cmd); } diff --git a/build_system/prepare.rs b/build_system/prepare.rs index 12aafdc1fb3..24a233d3806 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -18,7 +18,7 @@ pub(crate) fn prepare() { "abi-checker", "Gankra", "abi-checker", - "7c1571da6e43f9a37347623e7d5c7d51be664a7b", + "a2232d45f202846f5c02203c9f27355360f9a2ff", ); clone_repo_shallow_github( -- cgit 1.4.1-3-g733a5 From 69c6749aee93ee3c5dd3b9b394eef612d48dd6cd Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Fri, 12 Aug 2022 23:47:12 +0100 Subject: Disable some abi-checker tests --- build_system/prepare.rs | 1 + .../0029-abi-checker-Disable-failing-tests.patch | 36 ++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 patches/0029-abi-checker-Disable-failing-tests.patch diff --git a/build_system/prepare.rs b/build_system/prepare.rs index 24a233d3806..d23b7f00dcf 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -20,6 +20,7 @@ pub(crate) fn prepare() { "abi-checker", "a2232d45f202846f5c02203c9f27355360f9a2ff", ); + apply_patches("abi-checker", Path::new("abi-checker")); clone_repo_shallow_github( "rand", diff --git a/patches/0029-abi-checker-Disable-failing-tests.patch b/patches/0029-abi-checker-Disable-failing-tests.patch new file mode 100644 index 00000000000..526366a7598 --- /dev/null +++ b/patches/0029-abi-checker-Disable-failing-tests.patch @@ -0,0 +1,36 @@ +From 1a315ba225577dbbd1f449d9609f16f984f68708 Mon Sep 17 00:00:00 2001 +From: Afonso Bordado +Date: Fri, 12 Aug 2022 22:51:58 +0000 +Subject: [PATCH] Disable abi-checker tests + +--- + src/report.rs | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/src/report.rs b/src/report.rs +index 7346f5e..8347762 100644 +--- a/src/report.rs ++++ b/src/report.rs +@@ -45,6 +45,20 @@ pub fn get_test_rules(test: &TestKey, caller: &dyn AbiImpl, callee: &dyn AbiImpl + // + // THIS AREA RESERVED FOR VENDORS TO APPLY PATCHES + ++ // Currently MSVC has some broken ABI issues. Furthermore, they cause ++ // a STATUS_ACCESS_VIOLATION, so we can't even run them. Ensure that they compile and link. ++ if cfg!(windows) && (test.test_name == "bool" || test.test_name == "ui128") { ++ result.run = Link; ++ result.check = Pass(Link); ++ } ++ ++ // structs is broken in the current release of cranelift for aarch64. ++ // It has been fixed for cranelift 0.88: https://github.com/bytecodealliance/wasmtime/pull/4634 ++ if cfg!(target_arch = "aarch64") && test.test_name == "structs" { ++ result.run = Link; ++ result.check = Pass(Link); ++ } ++ + // END OF VENDOR RESERVED AREA + // + // +-- +2.34.1 -- cgit 1.4.1-3-g733a5 From 484041cefeab79874b5dd134a7e9b4b189e3c5a2 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 13 Aug 2022 10:02:16 +0100 Subject: Rename abi-checker patch (#1262) --- .../0001-abi-checker-Disable-failing-tests.patch | 36 ++++++++++++++++++++++ .../0029-abi-checker-Disable-failing-tests.patch | 36 ---------------------- 2 files changed, 36 insertions(+), 36 deletions(-) create mode 100644 patches/0001-abi-checker-Disable-failing-tests.patch delete mode 100644 patches/0029-abi-checker-Disable-failing-tests.patch diff --git a/patches/0001-abi-checker-Disable-failing-tests.patch b/patches/0001-abi-checker-Disable-failing-tests.patch new file mode 100644 index 00000000000..526366a7598 --- /dev/null +++ b/patches/0001-abi-checker-Disable-failing-tests.patch @@ -0,0 +1,36 @@ +From 1a315ba225577dbbd1f449d9609f16f984f68708 Mon Sep 17 00:00:00 2001 +From: Afonso Bordado +Date: Fri, 12 Aug 2022 22:51:58 +0000 +Subject: [PATCH] Disable abi-checker tests + +--- + src/report.rs | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/src/report.rs b/src/report.rs +index 7346f5e..8347762 100644 +--- a/src/report.rs ++++ b/src/report.rs +@@ -45,6 +45,20 @@ pub fn get_test_rules(test: &TestKey, caller: &dyn AbiImpl, callee: &dyn AbiImpl + // + // THIS AREA RESERVED FOR VENDORS TO APPLY PATCHES + ++ // Currently MSVC has some broken ABI issues. Furthermore, they cause ++ // a STATUS_ACCESS_VIOLATION, so we can't even run them. Ensure that they compile and link. ++ if cfg!(windows) && (test.test_name == "bool" || test.test_name == "ui128") { ++ result.run = Link; ++ result.check = Pass(Link); ++ } ++ ++ // structs is broken in the current release of cranelift for aarch64. ++ // It has been fixed for cranelift 0.88: https://github.com/bytecodealliance/wasmtime/pull/4634 ++ if cfg!(target_arch = "aarch64") && test.test_name == "structs" { ++ result.run = Link; ++ result.check = Pass(Link); ++ } ++ + // END OF VENDOR RESERVED AREA + // + // +-- +2.34.1 diff --git a/patches/0029-abi-checker-Disable-failing-tests.patch b/patches/0029-abi-checker-Disable-failing-tests.patch deleted file mode 100644 index 526366a7598..00000000000 --- a/patches/0029-abi-checker-Disable-failing-tests.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 1a315ba225577dbbd1f449d9609f16f984f68708 Mon Sep 17 00:00:00 2001 -From: Afonso Bordado -Date: Fri, 12 Aug 2022 22:51:58 +0000 -Subject: [PATCH] Disable abi-checker tests - ---- - src/report.rs | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/src/report.rs b/src/report.rs -index 7346f5e..8347762 100644 ---- a/src/report.rs -+++ b/src/report.rs -@@ -45,6 +45,20 @@ pub fn get_test_rules(test: &TestKey, caller: &dyn AbiImpl, callee: &dyn AbiImpl - // - // THIS AREA RESERVED FOR VENDORS TO APPLY PATCHES - -+ // Currently MSVC has some broken ABI issues. Furthermore, they cause -+ // a STATUS_ACCESS_VIOLATION, so we can't even run them. Ensure that they compile and link. -+ if cfg!(windows) && (test.test_name == "bool" || test.test_name == "ui128") { -+ result.run = Link; -+ result.check = Pass(Link); -+ } -+ -+ // structs is broken in the current release of cranelift for aarch64. -+ // It has been fixed for cranelift 0.88: https://github.com/bytecodealliance/wasmtime/pull/4634 -+ if cfg!(target_arch = "aarch64") && test.test_name == "structs" { -+ result.run = Link; -+ result.check = Pass(Link); -+ } -+ - // END OF VENDOR RESERVED AREA - // - // --- -2.34.1 -- cgit 1.4.1-3-g733a5 From 4c0766ce6cae86b0f340683d90a5ed02cace81f7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 13 Aug 2022 09:03:28 +0000 Subject: Move error reporting out of emit_cgu Error reporting requires a Session, which isn't available on background threads. --- src/driver/aot.rs | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 7e5e3453834..817ce7f7e6d 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -33,7 +33,7 @@ impl HashStable for ModuleCodegenResult { } pub(crate) struct OngoingCodegen { - modules: Vec, + modules: Vec>, allocator_module: Option, metadata_module: Option, metadata: EncodedMetadata, @@ -50,6 +50,10 @@ impl OngoingCodegen { let mut modules = vec![]; for module_codegen_result in self.modules { + let module_codegen_result = match module_codegen_result { + Ok(module_codegen_result) => module_codegen_result, + Err(err) => sess.fatal(&err), + }; let ModuleCodegenResult { module_regular, module_global_asm, existing_work_product } = module_codegen_result; @@ -117,7 +121,7 @@ fn emit_cgu( debug: Option>, unwind_context: UnwindContext, global_asm_object_file: Option, -) -> ModuleCodegenResult { +) -> Result { let mut product = module.finish(); if let Some(mut debug) = debug { @@ -126,9 +130,9 @@ fn emit_cgu( unwind_context.emit(&mut product); - let module_regular = emit_module(tcx, product.object, ModuleKind::Regular, name.clone()); + let module_regular = emit_module(tcx, product.object, ModuleKind::Regular, name.clone())?; - ModuleCodegenResult { + Ok(ModuleCodegenResult { module_regular, module_global_asm: global_asm_object_file.map(|global_asm_object_file| CompiledModule { name: format!("{name}.asm"), @@ -138,7 +142,7 @@ fn emit_cgu( bytecode: None, }), existing_work_product: None, - } + }) } fn emit_module( @@ -146,23 +150,26 @@ fn emit_module( object: cranelift_object::object::write::Object<'_>, kind: ModuleKind, name: String, -) -> CompiledModule { +) -> Result { let tmp_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(&name)); let mut file = match File::create(&tmp_file) { Ok(file) => file, - Err(err) => tcx.sess.fatal(&format!("error creating object file: {}", err)), + Err(err) => return Err(format!("error creating object file: {}", err)), }; if let Err(err) = object.write_stream(&mut file) { - tcx.sess.fatal(&format!("error writing object file: {}", err)); + return Err(format!("error writing object file: {}", err)); } tcx.sess.prof.artifact_size("object_file", &*name, file.metadata().unwrap().len()); - CompiledModule { name, kind, object: Some(tmp_file), dwarf_object: None, bytecode: None } + Ok(CompiledModule { name, kind, object: Some(tmp_file), dwarf_object: None, bytecode: None }) } -fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCodegenResult { +fn reuse_workproduct_for_cgu( + tcx: TyCtxt<'_>, + cgu: &CodegenUnit<'_>, +) -> Result { let work_product = cgu.previous_work_product(tcx); let obj_out_regular = tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str())); @@ -172,7 +179,7 @@ fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCo ); if let Err(err) = rustc_fs_util::link_or_copy(&source_file_regular, &obj_out_regular) { - tcx.sess.err(&format!( + return Err(format!( "unable to copy {} to {}: {}", source_file_regular.display(), obj_out_regular.display(), @@ -185,7 +192,7 @@ fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCo let source_file_global_asm = rustc_incremental::in_incr_comp_dir_sess(&tcx.sess, asm_o); if let Err(err) = rustc_fs_util::link_or_copy(&source_file_global_asm, &obj_out_global_asm) { - tcx.sess.err(&format!( + return Err(format!( "unable to copy {} to {}: {}", source_file_regular.display(), obj_out_regular.display(), @@ -197,7 +204,7 @@ fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCo false }; - ModuleCodegenResult { + Ok(ModuleCodegenResult { module_regular: CompiledModule { name: cgu.name().to_string(), kind: ModuleKind::Regular, @@ -217,7 +224,7 @@ fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCo None }, existing_work_product: Some((cgu.work_product_id(), work_product)), - } + }) } fn module_codegen( @@ -227,7 +234,7 @@ fn module_codegen( Arc, rustc_span::Symbol, ), -) -> ModuleCodegenResult { +) -> Result { let cgu = tcx.codegen_unit(cgu_name); let mono_items = cgu.items_in_deterministic_order(tcx); @@ -279,7 +286,7 @@ fn module_codegen( let debug_context = cx.debug_context; let unwind_context = cx.unwind_context; - let codegen_result = tcx.sess.time("write object file", || { + tcx.sess.time("write object file", || { emit_cgu( tcx, cgu.name().as_str().to_string(), @@ -288,9 +295,7 @@ fn module_codegen( unwind_context, global_asm_object_file, ) - }); - - codegen_result + }) } pub(crate) fn run_aot( @@ -356,7 +361,10 @@ pub(crate) fn run_aot( let mut product = allocator_module.finish(); allocator_unwind_context.emit(&mut product); - Some(emit_module(tcx, product.object, ModuleKind::Allocator, "allocator_shim".to_owned())) + match emit_module(tcx, product.object, ModuleKind::Allocator, "allocator_shim".to_owned()) { + Ok(allocator_module) => Some(allocator_module), + Err(err) => tcx.sess.fatal(err), + } } else { None }; -- cgit 1.4.1-3-g733a5 From 9461fd2cb061c7016207c22dc77f7ad906066279 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 13 Aug 2022 12:18:41 +0000 Subject: Remove TyCtxt parameter from emit_cgu TyCtxt isn't available on background threads. --- src/driver/aot.rs | 27 +++++++++++++++++++-------- src/global_asm.rs | 2 +- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 817ce7f7e6d..9d819e3995b 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -7,12 +7,13 @@ use std::sync::Arc; use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file; use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind}; +use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::mir::mono::{CodegenUnit, MonoItem}; use rustc_session::cgu_reuse_tracker::CguReuse; -use rustc_session::config::{DebugInfo, OutputType}; +use rustc_session::config::{DebugInfo, OutputFilenames, OutputType}; use rustc_session::Session; use cranelift_object::{ObjectBuilder, ObjectModule}; @@ -115,7 +116,8 @@ fn make_module(sess: &Session, backend_config: &BackendConfig, name: String) -> } fn emit_cgu( - tcx: TyCtxt<'_>, + output_filenames: &OutputFilenames, + prof: &SelfProfilerRef, name: String, module: ObjectModule, debug: Option>, @@ -130,7 +132,8 @@ fn emit_cgu( unwind_context.emit(&mut product); - let module_regular = emit_module(tcx, product.object, ModuleKind::Regular, name.clone())?; + let module_regular = + emit_module(output_filenames, prof, product.object, ModuleKind::Regular, name.clone())?; Ok(ModuleCodegenResult { module_regular, @@ -146,12 +149,13 @@ fn emit_cgu( } fn emit_module( - tcx: TyCtxt<'_>, + output_filenames: &OutputFilenames, + prof: &SelfProfilerRef, object: cranelift_object::object::write::Object<'_>, kind: ModuleKind, name: String, ) -> Result { - let tmp_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(&name)); + let tmp_file = output_filenames.temp_path(OutputType::Object, Some(&name)); let mut file = match File::create(&tmp_file) { Ok(file) => file, Err(err) => return Err(format!("error creating object file: {}", err)), @@ -161,7 +165,7 @@ fn emit_module( return Err(format!("error writing object file: {}", err)); } - tcx.sess.prof.artifact_size("object_file", &*name, file.metadata().unwrap().len()); + prof.artifact_size("object_file", &*name, file.metadata().unwrap().len()); Ok(CompiledModule { name, kind, object: Some(tmp_file), dwarf_object: None, bytecode: None }) } @@ -288,7 +292,8 @@ fn module_codegen( let unwind_context = cx.unwind_context; tcx.sess.time("write object file", || { emit_cgu( - tcx, + &global_asm_config.output_filenames, + &tcx.sess.prof, cgu.name().as_str().to_string(), module, debug_context, @@ -361,7 +366,13 @@ pub(crate) fn run_aot( let mut product = allocator_module.finish(); allocator_unwind_context.emit(&mut product); - match emit_module(tcx, product.object, ModuleKind::Allocator, "allocator_shim".to_owned()) { + match emit_module( + tcx.output_filenames(()), + &tcx.sess.prof, + product.object, + ModuleKind::Allocator, + "allocator_shim".to_owned(), + ) { Ok(allocator_module) => Some(allocator_module), Err(err) => tcx.sess.fatal(err), } diff --git a/src/global_asm.rs b/src/global_asm.rs index 917a6fff727..dcbcaba30fe 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -36,7 +36,7 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, pub(crate) struct GlobalAsmConfig { asm_enabled: bool, assembler: PathBuf, - output_filenames: Arc, + pub(crate) output_filenames: Arc, } impl GlobalAsmConfig { -- cgit 1.4.1-3-g733a5 From 4eebcb9910c1180791b0e5dba5b3192d0e0046a4 Mon Sep 17 00:00:00 2001 From: KaDiWa Date: Sat, 13 Aug 2022 15:50:01 +0200 Subject: avoid cloning and then iterating --- compiler/rustc_builtin_macros/src/deriving/generic/mod.rs | 3 +-- compiler/rustc_parse/src/parser/attr_wrapper.rs | 8 ++++---- compiler/rustc_parse/src/parser/diagnostics.rs | 2 +- compiler/rustc_resolve/src/late/diagnostics.rs | 2 +- compiler/rustc_trait_selection/src/traits/auto_trait.rs | 2 +- compiler/rustc_typeck/src/astconv/generics.rs | 5 ++--- compiler/rustc_typeck/src/check/upvar.rs | 2 +- src/librustdoc/clean/auto_trait.rs | 4 ++-- src/librustdoc/html/render/search_index.rs | 13 +++++++++---- src/librustdoc/json/mod.rs | 11 ++++++----- src/tools/compiletest/src/runtest.rs | 2 +- src/tools/unicode-table-generator/src/raw_emitter.rs | 8 ++------ 12 files changed, 31 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index ef64f52d40b..708a7eabc0f 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -385,8 +385,7 @@ fn find_type_parameters( // Place bound generic params on a stack, to extract them when a type is encountered. fn visit_poly_trait_ref(&mut self, trait_ref: &'a ast::PolyTraitRef) { let stack_len = self.bound_generic_params_stack.len(); - self.bound_generic_params_stack - .extend(trait_ref.bound_generic_params.clone().into_iter()); + self.bound_generic_params_stack.extend(trait_ref.bound_generic_params.iter().cloned()); visit::walk_poly_trait_ref(self, trait_ref); diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index 6c750ff428f..ca0ac7829b1 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -116,7 +116,7 @@ impl CreateTokenStream for LazyTokenStreamImpl { if !self.replace_ranges.is_empty() { let mut tokens: Vec<_> = tokens.collect(); - let mut replace_ranges = self.replace_ranges.clone(); + let mut replace_ranges = self.replace_ranges.to_vec(); replace_ranges.sort_by_key(|(range, _)| range.start); #[cfg(debug_assertions)] @@ -146,7 +146,7 @@ impl CreateTokenStream for LazyTokenStreamImpl { // start position, we ensure that any replace range which encloses // another replace range will capture the *replaced* tokens for the inner // range, not the original tokens. - for (range, new_tokens) in replace_ranges.iter().rev() { + for (range, new_tokens) in replace_ranges.into_iter().rev() { assert!(!range.is_empty(), "Cannot replace an empty range: {:?}", range); // Replace ranges are only allowed to decrease the number of tokens. assert!( @@ -165,7 +165,7 @@ impl CreateTokenStream for LazyTokenStreamImpl { tokens.splice( (range.start as usize)..(range.end as usize), - new_tokens.clone().into_iter().chain(filler), + new_tokens.into_iter().chain(filler), ); } make_token_stream(tokens.into_iter(), self.break_last_token) @@ -321,7 +321,7 @@ impl<'a> Parser<'a> { self.capture_state.replace_ranges[replace_ranges_start..replace_ranges_end] .iter() .cloned() - .chain(inner_attr_replace_ranges.clone().into_iter()) + .chain(inner_attr_replace_ranges.iter().cloned()) .map(|(range, tokens)| { ((range.start - start_calls)..(range.end - start_calls), tokens) }) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index f4c6b33a529..7f747785936 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -387,7 +387,7 @@ impl<'a> Parser<'a> { /// This is to avoid losing unclosed delims errors `create_snapshot_for_diagnostic` clears. pub(super) fn restore_snapshot(&mut self, snapshot: SnapshotParser<'a>) { *self = snapshot.parser; - self.unclosed_delims.extend(snapshot.unclosed_delims.clone()); + self.unclosed_delims.extend(snapshot.unclosed_delims); } pub fn unclosed_delims(&self) -> &[UnmatchedBrace] { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index cb133841bca..5cacd7fc681 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2300,7 +2300,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { err.multipart_suggestion_verbose( message, std::iter::once((span, intro_sugg)) - .chain(spans_suggs.clone()) + .chain(spans_suggs.iter().cloned()) .collect(), Applicability::MaybeIncorrect, ); diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 6b230210888..4bab9935501 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -341,7 +341,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { } } - let obligations = impl_source.clone().nested_obligations().into_iter(); + let obligations = impl_source.borrow_nested_obligations().iter().cloned(); if !self.evaluate_nested_obligations( ty, diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index 40aa27a29e9..ad0da4bed45 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -298,9 +298,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // show that order to the user as a possible order for the parameters let mut param_types_present = defs .params - .clone() - .into_iter() - .map(|param| (param.kind.to_ord(), param)) + .iter() + .map(|param| (param.kind.to_ord(), param.clone())) .collect::>(); param_types_present.sort_by_key(|(ord, _)| *ord); let (mut param_types_present, ordered_params): ( diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index dd8f943b985..0afc153300b 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -1217,7 +1217,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Combine all the reasons of why the root variable should be captured as a result of // auto trait implementation issues - auto_trait_migration_reasons.extend(capture_trait_reasons.clone()); + auto_trait_migration_reasons.extend(capture_trait_reasons.iter().copied()); diagnostics_info.push(MigrationLintNote { captures_info, diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index a94520b1219..029dc861674 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -525,8 +525,8 @@ where GenericBound::TraitBound(ref mut p, _) => { // Insert regions into the for_generics hash map first, to ensure // that we don't end up with duplicate bounds (e.g., for<'b, 'b>) - for_generics.extend(p.generic_params.clone()); - p.generic_params = for_generics.into_iter().collect(); + for_generics.extend(p.generic_params.drain(..)); + p.generic_params.extend(for_generics); self.is_fn_trait(&p.trait_) } _ => false, diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index d672f0bb599..8eb9c07f8a7 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -544,10 +544,15 @@ fn get_fn_inputs_and_outputs<'tcx>( (true, _) => (Some(impl_self), &func.generics), (_, true) => (Some(impl_self), impl_generics), (false, false) => { - let mut params = func.generics.params.clone(); - params.extend(impl_generics.params.clone()); - let mut where_predicates = func.generics.where_predicates.clone(); - where_predicates.extend(impl_generics.where_predicates.clone()); + let params = + func.generics.params.iter().chain(&impl_generics.params).cloned().collect(); + let where_predicates = func + .generics + .where_predicates + .iter() + .chain(&impl_generics.where_predicates) + .cloned() + .collect(); combined_generics = clean::Generics { params, where_predicates }; (Some(impl_self), &combined_generics) } diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 6364d00d062..a07668a2b6d 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -106,7 +106,9 @@ impl<'tcx> JsonRenderer<'tcx> { // only need to synthesize items for external traits if !id.is_local() { let trait_item = &trait_item.trait_; - trait_item.items.clone().into_iter().for_each(|i| self.item(i).unwrap()); + for item in &trait_item.items { + self.item(item.clone()).unwrap(); + } let item_id = from_item_id(id.into(), self.tcx); Some(( item_id.clone(), @@ -274,10 +276,9 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { paths: self .cache .paths - .clone() - .into_iter() - .chain(self.cache.external_paths.clone().into_iter()) - .map(|(k, (path, kind))| { + .iter() + .chain(&self.cache.external_paths) + .map(|(&k, &(ref path, kind))| { ( from_item_id(k.into(), self.tcx), types::ItemSummary { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 47f2a2d3482..6bd41a50a6d 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1702,7 +1702,7 @@ impl<'test> TestCx<'test> { fn compose_and_run_compiler(&self, mut rustc: Command, input: Option) -> ProcRes { let aux_dir = self.build_all_auxiliary(&mut rustc); - self.props.unset_rustc_env.clone().iter().fold(&mut rustc, |rustc, v| rustc.env_remove(v)); + self.props.unset_rustc_env.iter().fold(&mut rustc, Command::env_remove); rustc.envs(self.props.rustc_env.clone()); self.compose_and_run( rustc, diff --git a/src/tools/unicode-table-generator/src/raw_emitter.rs b/src/tools/unicode-table-generator/src/raw_emitter.rs index ab8eaee9541..38a4aa9d749 100644 --- a/src/tools/unicode-table-generator/src/raw_emitter.rs +++ b/src/tools/unicode-table-generator/src/raw_emitter.rs @@ -121,12 +121,8 @@ impl RawEmitter { for chunk in compressed_words.chunks(chunk_length) { chunks.insert(chunk); } - let chunk_map = chunks - .clone() - .into_iter() - .enumerate() - .map(|(idx, chunk)| (chunk, idx)) - .collect::>(); + let chunk_map = + chunks.iter().enumerate().map(|(idx, &chunk)| (chunk, idx)).collect::>(); let mut chunk_indices = Vec::new(); for chunk in compressed_words.chunks(chunk_length) { chunk_indices.push(chunk_map[chunk]); -- cgit 1.4.1-3-g733a5 From 786e8755e7f8142c90a82351a11ad51acf5e1460 Mon Sep 17 00:00:00 2001 From: Berend-Jan Lange Date: Fri, 22 Apr 2022 21:39:09 +0200 Subject: created tcpstream quickack trait for linux and android --- library/std/src/net/mod.rs | 2 +- library/std/src/os/android/mod.rs | 1 + library/std/src/os/android/net.rs | 4 +++ library/std/src/os/linux/mod.rs | 1 + library/std/src/os/linux/net.rs | 4 +++ library/std/src/os/mod.rs | 3 ++ library/std/src/os/net/mod.rs | 7 ++++ library/std/src/os/net/tcp.rs | 70 +++++++++++++++++++++++++++++++++++++++ library/std/src/os/net/tests.rs | 29 ++++++++++++++++ library/std/src/sys/unix/net.rs | 11 ++++++ library/std/src/sys_common/net.rs | 8 ++++- 11 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 library/std/src/os/android/net.rs create mode 100644 library/std/src/os/linux/net.rs create mode 100644 library/std/src/os/net/mod.rs create mode 100644 library/std/src/os/net/tcp.rs create mode 100644 library/std/src/os/net/tests.rs diff --git a/library/std/src/net/mod.rs b/library/std/src/net/mod.rs index e7a40bdaf8e..6f9743f3a0e 100644 --- a/library/std/src/net/mod.rs +++ b/library/std/src/net/mod.rs @@ -41,7 +41,7 @@ mod ip; mod parser; mod tcp; #[cfg(test)] -mod test; +pub(crate) mod test; mod udp; /// Possible values which can be passed to the [`TcpStream::shutdown`] method. diff --git a/library/std/src/os/android/mod.rs b/library/std/src/os/android/mod.rs index dbb0127f369..5adcb82b6a4 100644 --- a/library/std/src/os/android/mod.rs +++ b/library/std/src/os/android/mod.rs @@ -3,4 +3,5 @@ #![stable(feature = "raw_ext", since = "1.1.0")] pub mod fs; +pub mod net; pub mod raw; diff --git a/library/std/src/os/android/net.rs b/library/std/src/os/android/net.rs new file mode 100644 index 00000000000..ff96125c37b --- /dev/null +++ b/library/std/src/os/android/net.rs @@ -0,0 +1,4 @@ +//! Linux and Android-specific definitions for socket options. + +#![unstable(feature = "tcp_quickack", issue = "96256")] +pub use crate::os::net::tcp::TcpStreamExt; diff --git a/library/std/src/os/linux/mod.rs b/library/std/src/os/linux/mod.rs index 8e7776f6646..c17053011ad 100644 --- a/library/std/src/os/linux/mod.rs +++ b/library/std/src/os/linux/mod.rs @@ -4,5 +4,6 @@ #![doc(cfg(target_os = "linux"))] pub mod fs; +pub mod net; pub mod process; pub mod raw; diff --git a/library/std/src/os/linux/net.rs b/library/std/src/os/linux/net.rs new file mode 100644 index 00000000000..ff96125c37b --- /dev/null +++ b/library/std/src/os/linux/net.rs @@ -0,0 +1,4 @@ +//! Linux and Android-specific definitions for socket options. + +#![unstable(feature = "tcp_quickack", issue = "96256")] +pub use crate::os::net::tcp::TcpStreamExt; diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index 6fbaa42c768..18c64b51007 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -148,3 +148,6 @@ pub mod vxworks; #[cfg(any(unix, target_os = "wasi", doc))] mod fd; + +#[cfg(any(target_os = "linux", target_os = "android", doc))] +mod net; diff --git a/library/std/src/os/net/mod.rs b/library/std/src/os/net/mod.rs new file mode 100644 index 00000000000..d6d84d24ec4 --- /dev/null +++ b/library/std/src/os/net/mod.rs @@ -0,0 +1,7 @@ +//! Linux and Android-specific definitions for socket options. + +#![unstable(feature = "tcp_quickack", issue = "96256")] +#![doc(cfg(any(target_os = "linux", target_os = "android",)))] +pub mod tcp; +#[cfg(test)] +mod tests; diff --git a/library/std/src/os/net/tcp.rs b/library/std/src/os/net/tcp.rs new file mode 100644 index 00000000000..5e9ee65a415 --- /dev/null +++ b/library/std/src/os/net/tcp.rs @@ -0,0 +1,70 @@ +//! Linux and Android-specific tcp extensions to primitives in the [`std::net`] module. +//! +//! [`std::net`]: crate::net + +use crate::io; +use crate::net; +use crate::sealed::Sealed; +use crate::sys_common::AsInner; + +/// Os-specific extensions for [`TcpStream`] +/// +/// [`TcpStream`]: net::TcpStream +#[unstable(feature = "tcp_quickack", issue = "96256")] +pub trait TcpStreamExt: Sealed { + /// Enable or disable `TCP_QUICKACK`. + /// + /// This flag causes Linux to eagerly send ACKs rather than delaying them. + /// Linux may reset this flag after further operations on the socket. + /// + /// See [`man 7 tcp`](https://man7.org/linux/man-pages/man7/tcp.7.html) and + /// [TCP delayed acknowledgement](https://en.wikipedia.org/wiki/TCP_delayed_acknowledgment) + /// for more information. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(tcp_quickack)] + /// use std::net::TcpStream; + /// use std::os::linux::net::TcpStreamExt; + /// + /// let stream = TcpStream::connect("127.0.0.1:8080") + /// .expect("Couldn't connect to the server..."); + /// stream.set_quickack(true).expect("set_quickack call failed"); + /// ``` + #[unstable(feature = "tcp_quickack", issue = "96256")] + fn set_quickack(&self, quickack: bool) -> io::Result<()>; + + /// Gets the value of the `TCP_QUICKACK` option on this socket. + /// + /// For more information about this option, see [`TcpStreamExt::set_quickack`]. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(tcp_quickack)] + /// use std::net::TcpStream; + /// use std::os::linux::net::TcpStreamExt; + /// + /// let stream = TcpStream::connect("127.0.0.1:8080") + /// .expect("Couldn't connect to the server..."); + /// stream.set_quickack(true).expect("set_quickack call failed"); + /// assert_eq!(stream.quickack().unwrap_or(false), true); + /// ``` + #[unstable(feature = "tcp_quickack", issue = "96256")] + fn quickack(&self) -> io::Result; +} + +#[unstable(feature = "tcp_quickack", issue = "96256")] +impl Sealed for net::TcpStream {} + +#[unstable(feature = "tcp_quickack", issue = "96256")] +impl TcpStreamExt for net::TcpStream { + fn set_quickack(&self, quickack: bool) -> io::Result<()> { + self.as_inner().as_inner().set_quickack(quickack) + } + + fn quickack(&self) -> io::Result { + self.as_inner().as_inner().quickack() + } +} diff --git a/library/std/src/os/net/tests.rs b/library/std/src/os/net/tests.rs new file mode 100644 index 00000000000..4704e315691 --- /dev/null +++ b/library/std/src/os/net/tests.rs @@ -0,0 +1,29 @@ +#[cfg(any(target_os = "android", target_os = "linux",))] +#[test] +fn quickack() { + use crate::{ + net::{test::next_test_ip4, TcpListener, TcpStream}, + os::net::tcp::TcpStreamExt, + }; + + macro_rules! t { + ($e:expr) => { + match $e { + Ok(t) => t, + Err(e) => panic!("received error for `{}`: {}", stringify!($e), e), + } + }; + } + + let addr = next_test_ip4(); + let _listener = t!(TcpListener::bind(&addr)); + + let stream = t!(TcpStream::connect(&("localhost", addr.port()))); + + t!(stream.set_quickack(false)); + assert_eq!(false, t!(stream.quickack())); + t!(stream.set_quickack(true)); + assert_eq!(true, t!(stream.quickack())); + t!(stream.set_quickack(false)); + assert_eq!(false, t!(stream.quickack())); +} diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index 462a45b01ab..85dcfc747af 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -392,6 +392,17 @@ impl Socket { Ok(raw != 0) } + #[cfg(any(target_os = "android", target_os = "linux",))] + pub fn set_quickack(&self, quickack: bool) -> io::Result<()> { + setsockopt(self, libc::IPPROTO_TCP, libc::TCP_QUICKACK, quickack as c_int) + } + + #[cfg(any(target_os = "android", target_os = "linux",))] + pub fn quickack(&self) -> io::Result { + let raw: c_int = getsockopt(self, libc::IPPROTO_TCP, libc::TCP_QUICKACK)?; + Ok(raw != 0) + } + #[cfg(any(target_os = "android", target_os = "linux",))] pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { setsockopt(self, libc::SOL_SOCKET, libc::SO_PASSCRED, passcred as libc::c_int) diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs index 33d336c4317..3ad802afa8f 100644 --- a/library/std/src/sys_common/net.rs +++ b/library/std/src/sys_common/net.rs @@ -10,7 +10,7 @@ use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; use crate::ptr; use crate::sys::net::netc as c; use crate::sys::net::{cvt, cvt_gai, cvt_r, init, wrlen_t, Socket}; -use crate::sys_common::{FromInner, IntoInner}; +use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::Duration; use libc::{c_int, c_void}; @@ -345,6 +345,12 @@ impl TcpStream { } } +impl AsInner for TcpStream { + fn as_inner(&self) -> &Socket { + &self.inner + } +} + impl FromInner for TcpStream { fn from_inner(socket: Socket) -> TcpStream { TcpStream { inner: socket } -- cgit 1.4.1-3-g733a5 From 4b162141631e900f760752eacdd6d5e510ac4e42 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 13 Aug 2022 18:39:30 +0200 Subject: Ban references to `Self` in trait object substs for projection predicates too. --- compiler/rustc_typeck/src/astconv/mod.rs | 46 +++++++++++++++++------- src/test/ui/traits/alias/self-in-generics.rs | 7 ++++ src/test/ui/traits/alias/self-in-generics.stderr | 2 +- 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 1e6cb53f3ee..ff81747cafe 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -35,7 +35,7 @@ use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECT use rustc_span::edition::Edition; use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::symbol::{kw, Ident, Symbol}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::Span; use rustc_target::spec::abi; use rustc_trait_selection::traits; use rustc_trait_selection::traits::astconv_object_safety_violations; @@ -1458,16 +1458,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if ty == dummy_self { let param = &generics.params[index]; missing_type_params.push(param.name); - tcx.ty_error().into() + return tcx.ty_error().into(); } else if ty.walk().any(|arg| arg == dummy_self.into()) { references_self = true; - tcx.ty_error().into() - } else { - arg + return tcx.ty_error().into(); } - } else { - arg } + arg }) .collect(); let substs = tcx.intern_substs(&substs[..]); @@ -1506,13 +1503,36 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }); let existential_projections = bounds.projection_bounds.iter().map(|(bound, _)| { - bound.map_bound(|b| { - if b.projection_ty.self_ty() != dummy_self { - tcx.sess.delay_span_bug( - DUMMY_SP, - &format!("trait_ref_to_existential called on {:?} with non-dummy Self", b), - ); + bound.map_bound(|mut b| { + assert_eq!(b.projection_ty.self_ty(), dummy_self); + + // Like for trait refs, verify that `dummy_self` did not leak inside default type + // parameters. + let references_self = b.projection_ty.substs.iter().skip(1).any(|arg| { + if let ty::GenericArgKind::Type(ty) = arg.unpack() { + if ty == dummy_self || ty.walk().any(|arg| arg == dummy_self.into()) { + return true; + } + } + false + }); + if references_self { + tcx.sess + .delay_span_bug(span, "trait object projection bounds reference `Self`"); + let substs: Vec<_> = b + .projection_ty + .substs + .iter() + .map(|arg| { + if let ty::GenericArgKind::Type(_) = arg.unpack() { + return tcx.ty_error().into(); + } + arg + }) + .collect(); + b.projection_ty.substs = tcx.intern_substs(&substs[..]); } + ty::ExistentialProjection::erase_self_ty(tcx, b) }) }); diff --git a/src/test/ui/traits/alias/self-in-generics.rs b/src/test/ui/traits/alias/self-in-generics.rs index 6b99431f5bb..0bb6335f91e 100644 --- a/src/test/ui/traits/alias/self-in-generics.rs +++ b/src/test/ui/traits/alias/self-in-generics.rs @@ -1,3 +1,10 @@ +// astconv uses `FreshTy(0)` as a dummy `Self` type when instanciating trait objects. +// This `FreshTy(0)` can leak into substs, causing ICEs in several places. +// Using `save-analysis` triggers type-checking `f` that would be normally skipped +// as `type_of` emitted an error. +// +// compile-flags: -Zsave-analysis + #![feature(trait_alias)] pub trait SelfInput = Fn(&mut Self); diff --git a/src/test/ui/traits/alias/self-in-generics.stderr b/src/test/ui/traits/alias/self-in-generics.stderr index a1056872ea6..110d60e6e91 100644 --- a/src/test/ui/traits/alias/self-in-generics.stderr +++ b/src/test/ui/traits/alias/self-in-generics.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait alias `SelfInput` cannot be made into an object - --> $DIR/self-in-generics.rs:5:19 + --> $DIR/self-in-generics.rs:12:19 | LL | pub fn f(_f: &dyn SelfInput) {} | ^^^^^^^^^ -- cgit 1.4.1-3-g733a5 From 8509936e8f48c64c063b7ba858b881377007f416 Mon Sep 17 00:00:00 2001 From: Jakub Dąbek Date: Sun, 14 Aug 2022 11:01:04 +0200 Subject: Add mention of `BufReader` in `Read::bytes` docs --- library/std/src/io/mod.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 96addbd1a05..a16e2431ea9 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -883,6 +883,10 @@ pub trait Read { /// The yielded item is [`Ok`] if a byte was successfully read and [`Err`] /// otherwise. EOF is mapped to returning [`None`] from this iterator. /// + /// The default implementation calls `read` for each byte, + /// which can be very inefficient for data that's not in memory, + /// such as [`File`]. Consider using a [`BufReader`] in such cases. + /// /// # Examples /// /// [`File`]s implement `Read`: @@ -895,10 +899,11 @@ pub trait Read { /// ```no_run /// use std::io; /// use std::io::prelude::*; + /// use std::io::BufReader; /// use std::fs::File; /// /// fn main() -> io::Result<()> { - /// let f = File::open("foo.txt")?; + /// let f = BufReader::new(File::open("foo.txt")?); /// /// for byte in f.bytes() { /// println!("{}", byte.unwrap()); -- cgit 1.4.1-3-g733a5 From 1662702a881a2137b5c82b43394ffb40dc3e964a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 14 Aug 2022 16:37:30 +0000 Subject: Work around new asm! usage in measureme This is necessary to fix rustc bootstraps --- src/inline_asm.rs | 156 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 119 insertions(+), 37 deletions(-) diff --git a/src/inline_asm.rs b/src/inline_asm.rs index 7b1a39c675c..9221abb8225 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -20,10 +20,14 @@ pub(crate) fn codegen_inline_asm<'tcx>( // FIXME add .eh_frame unwind info directives if !template.is_empty() { + // Used by panic_abort if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) { fx.bcx.ins().trap(TrapCode::User(1)); return; - } else if template[0] == InlineAsmTemplatePiece::String("movq %rbx, ".to_string()) + } + + // Used by stdarch + if template[0] == InlineAsmTemplatePiece::String("movq %rbx, ".to_string()) && matches!( template[1], InlineAsmTemplatePiece::Placeholder { @@ -47,51 +51,46 @@ pub(crate) fn codegen_inline_asm<'tcx>( { assert_eq!(operands.len(), 4); let (leaf, eax_place) = match operands[1] { - InlineAsmOperand::InOut { reg, late: true, ref in_value, out_place } => { - assert_eq!( - reg, - InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)) - ); - ( - crate::base::codegen_operand(fx, in_value).load_scalar(fx), - crate::base::codegen_place(fx, out_place.unwrap()), - ) - } + InlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)), + late: true, + ref in_value, + out_place: Some(out_place), + } => ( + crate::base::codegen_operand(fx, in_value).load_scalar(fx), + crate::base::codegen_place(fx, out_place), + ), _ => unreachable!(), }; let ebx_place = match operands[0] { - InlineAsmOperand::Out { reg, late: true, place } => { - assert_eq!( - reg, + InlineAsmOperand::Out { + reg: InlineAsmRegOrRegClass::RegClass(InlineAsmRegClass::X86( - X86InlineAsmRegClass::reg - )) - ); - crate::base::codegen_place(fx, place.unwrap()) - } + X86InlineAsmRegClass::reg, + )), + late: true, + place: Some(place), + } => crate::base::codegen_place(fx, place), _ => unreachable!(), }; let (sub_leaf, ecx_place) = match operands[2] { - InlineAsmOperand::InOut { reg, late: true, ref in_value, out_place } => { - assert_eq!( - reg, - InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)) - ); - ( - crate::base::codegen_operand(fx, in_value).load_scalar(fx), - crate::base::codegen_place(fx, out_place.unwrap()), - ) - } + InlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)), + late: true, + ref in_value, + out_place: Some(out_place), + } => ( + crate::base::codegen_operand(fx, in_value).load_scalar(fx), + crate::base::codegen_place(fx, out_place), + ), _ => unreachable!(), }; let edx_place = match operands[3] { - InlineAsmOperand::Out { reg, late: true, place } => { - assert_eq!( - reg, - InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)) - ); - crate::base::codegen_place(fx, place.unwrap()) - } + InlineAsmOperand::Out { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)), + late: true, + place: Some(place), + } => crate::base::codegen_place(fx, place), _ => unreachable!(), }; @@ -104,7 +103,10 @@ pub(crate) fn codegen_inline_asm<'tcx>( let destination_block = fx.get_block(destination.unwrap()); fx.bcx.ins().jump(destination_block, &[]); return; - } else if fx.tcx.symbol_name(fx.instance).name.starts_with("___chkstk") { + } + + // Used by compiler-builtins + if fx.tcx.symbol_name(fx.instance).name.starts_with("___chkstk") { // ___chkstk, ___chkstk_ms and __alloca are only used on Windows crate::trap::trap_unimplemented(fx, "Stack probes are not supported"); return; @@ -112,6 +114,86 @@ pub(crate) fn codegen_inline_asm<'tcx>( crate::trap::trap_unimplemented(fx, "Alloca is not supported"); return; } + + // Used by measureme + if template[0] == InlineAsmTemplatePiece::String("xor %eax, %eax".to_string()) + && template[1] == InlineAsmTemplatePiece::String("\n".to_string()) + && template[2] == InlineAsmTemplatePiece::String("mov %rbx, ".to_string()) + && matches!( + template[3], + InlineAsmTemplatePiece::Placeholder { + operand_idx: 0, + modifier: Some('r'), + span: _ + } + ) + && template[4] == InlineAsmTemplatePiece::String("\n".to_string()) + && template[5] == InlineAsmTemplatePiece::String("cpuid".to_string()) + && template[6] == InlineAsmTemplatePiece::String("\n".to_string()) + && template[7] == InlineAsmTemplatePiece::String("mov ".to_string()) + && matches!( + template[8], + InlineAsmTemplatePiece::Placeholder { + operand_idx: 0, + modifier: Some('r'), + span: _ + } + ) + && template[9] == InlineAsmTemplatePiece::String(", %rbx".to_string()) + { + let destination_block = fx.get_block(destination.unwrap()); + fx.bcx.ins().jump(destination_block, &[]); + return; + } else if template[0] == InlineAsmTemplatePiece::String("rdpmc".to_string()) { + // Return zero dummy values for all performance counters + match operands[0] { + InlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)), + value: _, + } => {} + _ => unreachable!(), + }; + let lo = match operands[1] { + InlineAsmOperand::Out { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)), + late: true, + place: Some(place), + } => crate::base::codegen_place(fx, place), + _ => unreachable!(), + }; + let hi = match operands[2] { + InlineAsmOperand::Out { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)), + late: true, + place: Some(place), + } => crate::base::codegen_place(fx, place), + _ => unreachable!(), + }; + + let u32_layout = fx.layout_of(fx.tcx.types.u32); + let zero = fx.bcx.ins().iconst(types::I32, 0); + lo.write_cvalue(fx, CValue::by_val(zero, u32_layout)); + hi.write_cvalue(fx, CValue::by_val(zero, u32_layout)); + + let destination_block = fx.get_block(destination.unwrap()); + fx.bcx.ins().jump(destination_block, &[]); + return; + } else if template[0] == InlineAsmTemplatePiece::String("lock xadd ".to_string()) + && matches!( + template[1], + InlineAsmTemplatePiece::Placeholder { operand_idx: 1, modifier: None, span: _ } + ) + && template[2] == InlineAsmTemplatePiece::String(", (".to_string()) + && matches!( + template[3], + InlineAsmTemplatePiece::Placeholder { operand_idx: 0, modifier: None, span: _ } + ) + && template[4] == InlineAsmTemplatePiece::String(")".to_string()) + { + let destination_block = fx.get_block(destination.unwrap()); + fx.bcx.ins().jump(destination_block, &[]); + return; + } } let mut inputs = Vec::new(); -- cgit 1.4.1-3-g733a5 From 84ba2289fdd3c41ebbef53de3fdb5035f2e73e60 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 6 Aug 2022 00:17:16 +0000 Subject: Suggest as_ref or as_mut --- compiler/rustc_borrowck/src/diagnostics/mod.rs | 2 +- src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr | 2 +- src/test/ui/suggestions/as-ref-2.stderr | 2 +- src/test/ui/suggestions/option-content-move.stderr | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 098e8de9420..cc5a3e16c96 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -1089,7 +1089,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if is_option_or_result && maybe_reinitialized_locations_is_empty { err.span_suggestion_verbose( fn_call_span.shrink_to_lo(), - "consider calling `.as_ref()` to borrow the type's contents", + "consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents", "as_ref().", Applicability::MachineApplicable, ); diff --git a/src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr b/src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr index af26169c806..17546f73836 100644 --- a/src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr +++ b/src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr @@ -12,7 +12,7 @@ note: this function takes ownership of the receiver `self`, which moves `*cb` | LL | pub const fn map(self, f: F) -> Option | ^^^^ -help: consider calling `.as_ref()` to borrow the type's contents +help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents | LL | cb.as_ref().map(|cb| cb()); | +++++++++ diff --git a/src/test/ui/suggestions/as-ref-2.stderr b/src/test/ui/suggestions/as-ref-2.stderr index 3c9d0f72abe..08b9fb1abd7 100644 --- a/src/test/ui/suggestions/as-ref-2.stderr +++ b/src/test/ui/suggestions/as-ref-2.stderr @@ -13,7 +13,7 @@ note: this function takes ownership of the receiver `self`, which moves `foo` | LL | pub const fn map(self, f: F) -> Option | ^^^^ -help: consider calling `.as_ref()` to borrow the type's contents +help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents | LL | let _x: Option = foo.as_ref().map(|s| bar(&s)); | +++++++++ diff --git a/src/test/ui/suggestions/option-content-move.stderr b/src/test/ui/suggestions/option-content-move.stderr index fccfbe1d744..d008971e438 100644 --- a/src/test/ui/suggestions/option-content-move.stderr +++ b/src/test/ui/suggestions/option-content-move.stderr @@ -11,7 +11,7 @@ note: this function takes ownership of the receiver `self`, which moves `selecti | LL | pub const fn unwrap(self) -> T { | ^^^^ -help: consider calling `.as_ref()` to borrow the type's contents +help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents | LL | if selection.1.as_ref().unwrap().contains(selection.0) { | +++++++++ @@ -29,7 +29,7 @@ note: this function takes ownership of the receiver `self`, which moves `selecti | LL | pub fn unwrap(self) -> T | ^^^^ -help: consider calling `.as_ref()` to borrow the type's contents +help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents | LL | if selection.1.as_ref().unwrap().contains(selection.0) { | +++++++++ -- cgit 1.4.1-3-g733a5 From 34e0d9a0bb409bb6c7fc45f1c222340b02989b8b Mon Sep 17 00:00:00 2001 From: cameron Date: Sun, 14 Aug 2022 23:07:47 +0100 Subject: suggest lazy-static for non-const statics --- compiler/rustc_const_eval/src/transform/check_consts/ops.rs | 5 +++++ src/test/ui/borrowck/issue-64453.stderr | 1 + src/test/ui/check-static-values-constraints.stderr | 1 + src/test/ui/consts/issue-32829-2.stderr | 2 ++ src/test/ui/consts/mir_check_nonconst.stderr | 1 + src/test/ui/issues/issue-16538.mir.stderr | 1 + src/test/ui/issues/issue-16538.thir.stderr | 1 + src/test/ui/issues/issue-25901.stderr | 1 + src/test/ui/static/static-vec-repeat-not-constant.stderr | 1 + 9 files changed, 14 insertions(+) diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 33802261644..c9cfc1f3f46 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -1,6 +1,7 @@ //! Concrete error types for all operations which may be invalid in a certain const context. use hir::def_id::LocalDefId; +use hir::ConstContext; use rustc_errors::{ error_code, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, }; @@ -331,6 +332,10 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { ccx.const_kind(), )); + if let ConstContext::Static(_) = ccx.const_kind() { + err.note("consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell"); + } + err } } diff --git a/src/test/ui/borrowck/issue-64453.stderr b/src/test/ui/borrowck/issue-64453.stderr index 1f8a1acb89f..245c3a40e05 100644 --- a/src/test/ui/borrowck/issue-64453.stderr +++ b/src/test/ui/borrowck/issue-64453.stderr @@ -14,6 +14,7 @@ LL | static settings_dir: String = format!(""); | ^^^^^^^^^^^ | = note: calls in statics are limited to constant functions, tuple structs and tuple variants + = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0507]: cannot move out of static item `settings_dir` diff --git a/src/test/ui/check-static-values-constraints.stderr b/src/test/ui/check-static-values-constraints.stderr index b28cf0d6bd0..3c193ca34ac 100644 --- a/src/test/ui/check-static-values-constraints.stderr +++ b/src/test/ui/check-static-values-constraints.stderr @@ -22,6 +22,7 @@ LL | field2: SafeEnum::Variant4("str".to_string()) | ^^^^^^^^^^^ | = note: calls in statics are limited to constant functions, tuple structs and tuple variants + = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell error[E0010]: allocations are not allowed in statics --> $DIR/check-static-values-constraints.rs:94:5 diff --git a/src/test/ui/consts/issue-32829-2.stderr b/src/test/ui/consts/issue-32829-2.stderr index b94bdc0e3df..0fec3581873 100644 --- a/src/test/ui/consts/issue-32829-2.stderr +++ b/src/test/ui/consts/issue-32829-2.stderr @@ -13,6 +13,7 @@ LL | invalid(); | ^^^^^^^^^ | = note: calls in statics are limited to constant functions, tuple structs and tuple variants + = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell error[E0015]: cannot call non-const fn `invalid` in statics --> $DIR/issue-32829-2.rs:54:9 @@ -21,6 +22,7 @@ LL | invalid(); | ^^^^^^^^^ | = note: calls in statics are limited to constant functions, tuple structs and tuple variants + = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell error: aborting due to 3 previous errors diff --git a/src/test/ui/consts/mir_check_nonconst.stderr b/src/test/ui/consts/mir_check_nonconst.stderr index 2bac995eebf..1e0652722ff 100644 --- a/src/test/ui/consts/mir_check_nonconst.stderr +++ b/src/test/ui/consts/mir_check_nonconst.stderr @@ -5,6 +5,7 @@ LL | static foo: Foo = bar(); | ^^^^^ | = note: calls in statics are limited to constant functions, tuple structs and tuple variants + = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell error: aborting due to previous error diff --git a/src/test/ui/issues/issue-16538.mir.stderr b/src/test/ui/issues/issue-16538.mir.stderr index 7dab7de7619..e320df4b7ad 100644 --- a/src/test/ui/issues/issue-16538.mir.stderr +++ b/src/test/ui/issues/issue-16538.mir.stderr @@ -5,6 +5,7 @@ LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: calls in statics are limited to constant functions, tuple structs and tuple variants + = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell error[E0133]: use of extern static is unsafe and requires unsafe function or block --> $DIR/issue-16538.rs:14:30 diff --git a/src/test/ui/issues/issue-16538.thir.stderr b/src/test/ui/issues/issue-16538.thir.stderr index a18b0197d87..4a862869274 100644 --- a/src/test/ui/issues/issue-16538.thir.stderr +++ b/src/test/ui/issues/issue-16538.thir.stderr @@ -21,6 +21,7 @@ LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: calls in statics are limited to constant functions, tuple structs and tuple variants + = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-25901.stderr b/src/test/ui/issues/issue-25901.stderr index e933745c44e..c6c80e41cf6 100644 --- a/src/test/ui/issues/issue-25901.stderr +++ b/src/test/ui/issues/issue-25901.stderr @@ -16,6 +16,7 @@ note: impl defined here, but it is not `const` LL | impl Deref for A { | ^^^^^^^^^^^^^^^^ = note: calls in statics are limited to constant functions, tuple structs and tuple variants + = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell error: aborting due to previous error diff --git a/src/test/ui/static/static-vec-repeat-not-constant.stderr b/src/test/ui/static/static-vec-repeat-not-constant.stderr index 84fc638a973..dec0123184d 100644 --- a/src/test/ui/static/static-vec-repeat-not-constant.stderr +++ b/src/test/ui/static/static-vec-repeat-not-constant.stderr @@ -5,6 +5,7 @@ LL | static a: [isize; 2] = [foo(); 2]; | ^^^^^ | = note: calls in statics are limited to constant functions, tuple structs and tuple variants + = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell error: aborting due to previous error -- cgit 1.4.1-3-g733a5 From 7680c8b69051536a9c4ebcf943b394526af1a1be Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 6 Aug 2022 19:50:01 -0700 Subject: Properly forward `ByRefSized::fold` to the inner iterator --- library/core/src/iter/adapters/by_ref_sized.rs | 29 ++++++++++++++---------- library/core/tests/iter/adapters/by_ref_sized.rs | 20 ++++++++++++++++ library/core/tests/iter/adapters/mod.rs | 1 + 3 files changed, 38 insertions(+), 12 deletions(-) create mode 100644 library/core/tests/iter/adapters/by_ref_sized.rs diff --git a/library/core/src/iter/adapters/by_ref_sized.rs b/library/core/src/iter/adapters/by_ref_sized.rs index cc1e8e8a27f..477e7117c3e 100644 --- a/library/core/src/iter/adapters/by_ref_sized.rs +++ b/library/core/src/iter/adapters/by_ref_sized.rs @@ -1,4 +1,4 @@ -use crate::ops::Try; +use crate::ops::{NeverShortCircuit, Try}; /// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics. /// @@ -8,28 +8,31 @@ use crate::ops::Try; #[derive(Debug)] pub struct ByRefSized<'a, I>(pub &'a mut I); +// The following implementations use UFCS-style, rather than trusting autoderef, +// to avoid accidentally calling the `&mut Iterator` implementations. + #[unstable(feature = "std_internals", issue = "none")] impl Iterator for ByRefSized<'_, I> { type Item = I::Item; #[inline] fn next(&mut self) -> Option { - self.0.next() + I::next(self.0) } #[inline] fn size_hint(&self) -> (usize, Option) { - self.0.size_hint() + I::size_hint(self.0) } #[inline] fn advance_by(&mut self, n: usize) -> Result<(), usize> { - self.0.advance_by(n) + I::advance_by(self.0, n) } #[inline] fn nth(&mut self, n: usize) -> Option { - self.0.nth(n) + I::nth(self.0, n) } #[inline] @@ -37,7 +40,8 @@ impl Iterator for ByRefSized<'_, I> { where F: FnMut(B, Self::Item) -> B, { - self.0.fold(init, f) + // `fold` needs ownership, so this can't forward directly. + I::try_fold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0 } #[inline] @@ -46,7 +50,7 @@ impl Iterator for ByRefSized<'_, I> { F: FnMut(B, Self::Item) -> R, R: Try, { - self.0.try_fold(init, f) + I::try_fold(self.0, init, f) } } @@ -54,17 +58,17 @@ impl Iterator for ByRefSized<'_, I> { impl DoubleEndedIterator for ByRefSized<'_, I> { #[inline] fn next_back(&mut self) -> Option { - self.0.next_back() + I::next_back(self.0) } #[inline] fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { - self.0.advance_back_by(n) + I::advance_back_by(self.0, n) } #[inline] fn nth_back(&mut self, n: usize) -> Option { - self.0.nth_back(n) + I::nth_back(self.0, n) } #[inline] @@ -72,7 +76,8 @@ impl DoubleEndedIterator for ByRefSized<'_, I> { where F: FnMut(B, Self::Item) -> B, { - self.0.rfold(init, f) + // `rfold` needs ownership, so this can't forward directly. + I::try_rfold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0 } #[inline] @@ -81,6 +86,6 @@ impl DoubleEndedIterator for ByRefSized<'_, I> { F: FnMut(B, Self::Item) -> R, R: Try, { - self.0.try_rfold(init, f) + I::try_rfold(self.0, init, f) } } diff --git a/library/core/tests/iter/adapters/by_ref_sized.rs b/library/core/tests/iter/adapters/by_ref_sized.rs new file mode 100644 index 00000000000..a9c066f0e8c --- /dev/null +++ b/library/core/tests/iter/adapters/by_ref_sized.rs @@ -0,0 +1,20 @@ +use core::iter::*; + +#[test] +fn test_iterator_by_ref_sized() { + let a = ['a', 'b', 'c', 'd']; + + let mut s = String::from("Z"); + let mut it = a.iter().copied(); + ByRefSized(&mut it).take(2).for_each(|x| s.push(x)); + assert_eq!(s, "Zab"); + ByRefSized(&mut it).fold((), |(), x| s.push(x)); + assert_eq!(s, "Zabcd"); + + let mut s = String::from("Z"); + let mut it = a.iter().copied(); + ByRefSized(&mut it).rev().take(2).for_each(|x| s.push(x)); + assert_eq!(s, "Zdc"); + ByRefSized(&mut it).rfold((), |(), x| s.push(x)); + assert_eq!(s, "Zdcba"); +} diff --git a/library/core/tests/iter/adapters/mod.rs b/library/core/tests/iter/adapters/mod.rs index 96539c0c394..ffd5f3857ae 100644 --- a/library/core/tests/iter/adapters/mod.rs +++ b/library/core/tests/iter/adapters/mod.rs @@ -1,4 +1,5 @@ mod array_chunks; +mod by_ref_sized; mod chain; mod cloned; mod copied; -- cgit 1.4.1-3-g733a5 From 40dcf89a26bde41734f6c3eb71d9eb6420e45ef8 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Mon, 15 Aug 2022 16:10:31 +0900 Subject: suggest adding a missing semicolon before an item --- compiler/rustc_ast/src/token.rs | 24 +++++++ compiler/rustc_parse/src/parser/diagnostics.rs | 6 +- .../parser/recover-missing-semi-before-item.fixed | 61 ++++++++++++++++ .../ui/parser/recover-missing-semi-before-item.rs | 61 ++++++++++++++++ .../parser/recover-missing-semi-before-item.stderr | 83 ++++++++++++++++++++++ 5 files changed, 233 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/parser/recover-missing-semi-before-item.fixed create mode 100644 src/test/ui/parser/recover-missing-semi-before-item.rs create mode 100644 src/test/ui/parser/recover-missing-semi-before-item.stderr diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 85d9687c600..dd98946b4cc 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -436,6 +436,30 @@ impl Token { || self == &OpenDelim(Delimiter::Parenthesis) } + /// Returns `true` if the token can appear at the start of an item. + pub fn can_begin_item(&self) -> bool { + match self.kind { + Ident(name, _) => [ + kw::Fn, + kw::Use, + kw::Struct, + kw::Enum, + kw::Pub, + kw::Trait, + kw::Extern, + kw::Impl, + kw::Unsafe, + kw::Static, + kw::Union, + kw::Macro, + kw::Mod, + kw::Type, + ] + .contains(&name), + _ => false, + } + } + /// Returns `true` if the token is any literal. pub fn is_lit(&self) -> bool { matches!(self.kind, Literal(..)) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index f4c6b33a529..d0fb768caa6 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -555,10 +555,12 @@ impl<'a> Parser<'a> { return Ok(true); } else if self.look_ahead(0, |t| { t == &token::CloseDelim(Delimiter::Brace) - || (t.can_begin_expr() && t != &token::Semi && t != &token::Pound) + || ((t.can_begin_expr() || t.can_begin_item()) + && t != &token::Semi + && t != &token::Pound) // Avoid triggering with too many trailing `#` in raw string. || (sm.is_multiline( - self.prev_token.span.shrink_to_hi().until(self.token.span.shrink_to_lo()) + self.prev_token.span.shrink_to_hi().until(self.token.span.shrink_to_lo()), ) && t == &token::Pound) }) && !expected.contains(&TokenType::Token(token::Comma)) { diff --git a/src/test/ui/parser/recover-missing-semi-before-item.fixed b/src/test/ui/parser/recover-missing-semi-before-item.fixed new file mode 100644 index 00000000000..0be17e69e8f --- /dev/null +++ b/src/test/ui/parser/recover-missing-semi-before-item.fixed @@ -0,0 +1,61 @@ +// run-rustfix + +#![allow(unused_variables, dead_code)] + +fn for_struct() { + let foo = 3; //~ ERROR expected `;`, found keyword `struct` + struct Foo; +} + +fn for_union() { + let foo = 3; //~ ERROR expected `;`, found `union` + union Foo { + foo: usize, + } +} + +fn for_enum() { + let foo = 3; //~ ERROR expected `;`, found keyword `enum` + enum Foo { + Bar, + } +} + +fn for_fn() { + let foo = 3; //~ ERROR expected `;`, found keyword `fn` + fn foo() {} +} + +fn for_extern() { + let foo = 3; //~ ERROR expected `;`, found keyword `extern` + extern fn foo() {} +} + +fn for_impl() { + struct Foo; + let foo = 3; //~ ERROR expected `;`, found keyword `impl` + impl Foo {} +} + +fn for_use() { + let foo = 3; //~ ERROR expected `;`, found keyword `pub` + pub use bar::Bar; +} + +fn for_mod() { + let foo = 3; //~ ERROR expected `;`, found keyword `mod` + mod foo {} +} + +fn for_type() { + let foo = 3; //~ ERROR expected `;`, found keyword `type` + type Foo = usize; +} + +mod bar { + pub struct Bar; +} + +const X: i32 = 123; //~ ERROR expected `;`, found keyword `fn` + +fn main() {} diff --git a/src/test/ui/parser/recover-missing-semi-before-item.rs b/src/test/ui/parser/recover-missing-semi-before-item.rs new file mode 100644 index 00000000000..867b7b749bb --- /dev/null +++ b/src/test/ui/parser/recover-missing-semi-before-item.rs @@ -0,0 +1,61 @@ +// run-rustfix + +#![allow(unused_variables, dead_code)] + +fn for_struct() { + let foo = 3 //~ ERROR expected `;`, found keyword `struct` + struct Foo; +} + +fn for_union() { + let foo = 3 //~ ERROR expected `;`, found `union` + union Foo { + foo: usize, + } +} + +fn for_enum() { + let foo = 3 //~ ERROR expected `;`, found keyword `enum` + enum Foo { + Bar, + } +} + +fn for_fn() { + let foo = 3 //~ ERROR expected `;`, found keyword `fn` + fn foo() {} +} + +fn for_extern() { + let foo = 3 //~ ERROR expected `;`, found keyword `extern` + extern fn foo() {} +} + +fn for_impl() { + struct Foo; + let foo = 3 //~ ERROR expected `;`, found keyword `impl` + impl Foo {} +} + +fn for_use() { + let foo = 3 //~ ERROR expected `;`, found keyword `pub` + pub use bar::Bar; +} + +fn for_mod() { + let foo = 3 //~ ERROR expected `;`, found keyword `mod` + mod foo {} +} + +fn for_type() { + let foo = 3 //~ ERROR expected `;`, found keyword `type` + type Foo = usize; +} + +mod bar { + pub struct Bar; +} + +const X: i32 = 123 //~ ERROR expected `;`, found keyword `fn` + +fn main() {} diff --git a/src/test/ui/parser/recover-missing-semi-before-item.stderr b/src/test/ui/parser/recover-missing-semi-before-item.stderr new file mode 100644 index 00000000000..61c43f2f189 --- /dev/null +++ b/src/test/ui/parser/recover-missing-semi-before-item.stderr @@ -0,0 +1,83 @@ +error: expected `;`, found keyword `struct` + --> $DIR/recover-missing-semi-before-item.rs:6:16 + | +LL | let foo = 3 + | ^ help: add `;` here +LL | struct Foo; + | ------ unexpected token + +error: expected `;`, found `union` + --> $DIR/recover-missing-semi-before-item.rs:11:16 + | +LL | let foo = 3 + | ^ help: add `;` here +LL | union Foo { + | ----- unexpected token + +error: expected `;`, found keyword `enum` + --> $DIR/recover-missing-semi-before-item.rs:18:16 + | +LL | let foo = 3 + | ^ help: add `;` here +LL | enum Foo { + | ---- unexpected token + +error: expected `;`, found keyword `fn` + --> $DIR/recover-missing-semi-before-item.rs:25:16 + | +LL | let foo = 3 + | ^ help: add `;` here +LL | fn foo() {} + | -- unexpected token + +error: expected `;`, found keyword `extern` + --> $DIR/recover-missing-semi-before-item.rs:30:16 + | +LL | let foo = 3 + | ^ help: add `;` here +LL | extern fn foo() {} + | ------ unexpected token + +error: expected `;`, found keyword `impl` + --> $DIR/recover-missing-semi-before-item.rs:36:16 + | +LL | let foo = 3 + | ^ help: add `;` here +LL | impl Foo {} + | ---- unexpected token + +error: expected `;`, found keyword `pub` + --> $DIR/recover-missing-semi-before-item.rs:41:16 + | +LL | let foo = 3 + | ^ help: add `;` here +LL | pub use bar::Bar; + | --- unexpected token + +error: expected `;`, found keyword `mod` + --> $DIR/recover-missing-semi-before-item.rs:46:16 + | +LL | let foo = 3 + | ^ help: add `;` here +LL | mod foo {} + | --- unexpected token + +error: expected `;`, found keyword `type` + --> $DIR/recover-missing-semi-before-item.rs:51:16 + | +LL | let foo = 3 + | ^ help: add `;` here +LL | type Foo = usize; + | ---- unexpected token + +error: expected `;`, found keyword `fn` + --> $DIR/recover-missing-semi-before-item.rs:59:19 + | +LL | const X: i32 = 123 + | ^ help: add `;` here +LL | +LL | fn main() {} + | -- unexpected token + +error: aborting due to 10 previous errors + -- cgit 1.4.1-3-g733a5 From 04681898f09dad23b2d282a541e1a3b181bed33e Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Tue, 7 Sep 2021 18:46:49 +0200 Subject: Added next_up and next_down for f32/f64. --- library/core/src/num/f32.rs | 98 ++++++++++++++++++++++++++++++++++++++++++++ library/core/src/num/f64.rs | 98 ++++++++++++++++++++++++++++++++++++++++++++ library/std/src/f32/tests.rs | 63 ++++++++++++++++++++++++++++ library/std/src/f64/tests.rs | 63 ++++++++++++++++++++++++++++ library/std/src/lib.rs | 1 + 5 files changed, 323 insertions(+) diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 6548ad2e514..7c38d830636 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -678,6 +678,104 @@ impl f32 { unsafe { mem::transmute::(self) & 0x8000_0000 != 0 } } + /// Returns the least number greater than `self`. + /// + /// Let `TINY` be the smallest representable positive `f32`. Then, + /// - if `self.is_nan()`, this returns `self`; + /// - if `self` is [`NEG_INFINITY`], this returns [`MIN`]; + /// - if `self` is `-TINY`, this returns -0.0; + /// - if `self` is -0.0 or +0.0, this returns `TINY`; + /// - if `self` is [`MAX`] or [`INFINITY`], this returns [`INFINITY`]; + /// - otherwise the unique least value greater than `self` is returned. + /// + /// The identity `x.next_up() == -(-x).next_down()` holds for all `x`. When `x` + /// is finite `x == x.next_up().next_down()` also holds. + /// + /// ```rust + /// #![feature(float_next_up_down)] + /// // f32::EPSILON is the difference between 1.0 and the next number up. + /// assert_eq!(1.0f32.next_up(), 1.0 + f32::EPSILON); + /// // But not for most numbers. + /// assert!(0.1f32.next_up() < 0.1 + f32::EPSILON); + /// assert_eq!(16777216f32.next_up(), 16777218.0); + /// ``` + /// + /// [`NEG_INFINITY`]: Self::NEG_INFINITY + /// [`INFINITY`]: Self::INFINITY + /// [`MIN`]: Self::MIN + /// [`MAX`]: Self::MAX + #[unstable(feature = "float_next_up_down", issue = "none")] + pub const fn next_up(self) -> Self { + // We must use strictly integer arithmetic to prevent denormals from + // flushing to zero after an arithmetic operation on some platforms. + const TINY_BITS: u32 = 0x1; // Smallest positive f32. + const CLEAR_SIGN_MASK: u32 = 0x7fff_ffff; + + let bits = self.to_bits(); + if self.is_nan() || bits == Self::INFINITY.to_bits() { + return self; + } + + let abs = bits & CLEAR_SIGN_MASK; + let next_bits = if abs == 0 { + TINY_BITS + } else if bits == abs { + bits + 1 + } else { + bits - 1 + }; + Self::from_bits(next_bits) + } + + /// Returns the greatest number less than `self`. + /// + /// Let `TINY` be the smallest representable positive `f32`. Then, + /// - if `self.is_nan()`, this returns `self`; + /// - if `self` is [`INFINITY`], this returns [`MAX`]; + /// - if `self` is `TINY`, this returns 0.0; + /// - if `self` is -0.0 or +0.0, this returns `-TINY`; + /// - if `self` is [`MIN`] or [`NEG_INFINITY`], this returns [`NEG_INFINITY`]; + /// - otherwise the unique greatest value less than `self` is returned. + /// + /// The identity `x.next_down() == -(-x).next_up()` holds for all `x`. When `x` + /// is finite `x == x.next_down().next_up()` also holds. + /// + /// ```rust + /// #![feature(float_next_up_down)] + /// let x = 1.0f32; + /// // Clamp value into range [0, 1). + /// let clamped = x.clamp(0.0, 1.0f32.next_down()); + /// assert!(clamped < 1.0); + /// assert_eq!(clamped.next_up(), 1.0); + /// ``` + /// + /// [`NEG_INFINITY`]: Self::NEG_INFINITY + /// [`INFINITY`]: Self::INFINITY + /// [`MIN`]: Self::MIN + /// [`MAX`]: Self::MAX + #[unstable(feature = "float_next_up_down", issue = "none")] + pub const fn next_down(self) -> Self { + // We must use strictly integer arithmetic to prevent denormals from + // flushing to zero after an arithmetic operation on some platforms. + const NEG_TINY_BITS: u32 = 0x8000_0001; // Smallest (in magnitude) negative f32. + const CLEAR_SIGN_MASK: u32 = 0x7fff_ffff; + + let bits = self.to_bits(); + if self.is_nan() || bits == Self::NEG_INFINITY.to_bits() { + return self; + } + + let abs = bits & CLEAR_SIGN_MASK; + let next_bits = if abs == 0 { + NEG_TINY_BITS + } else if bits == abs { + bits - 1 + } else { + bits + 1 + }; + Self::from_bits(next_bits) + } + /// Takes the reciprocal (inverse) of a number, `1/x`. /// /// ``` diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 75c92c2f883..8146f007531 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -688,6 +688,104 @@ impl f64 { self.is_sign_negative() } + /// Returns the least number greater than `self`. + /// + /// Let `TINY` be the smallest representable positive `f64`. Then, + /// - if `self.is_nan()`, this returns `self`; + /// - if `self` is [`NEG_INFINITY`], this returns [`MIN`]; + /// - if `self` is `-TINY`, this returns -0.0; + /// - if `self` is -0.0 or +0.0, this returns `TINY`; + /// - if `self` is [`MAX`] or [`INFINITY`], this returns [`INFINITY`]; + /// - otherwise the unique least value greater than `self` is returned. + /// + /// The identity `x.next_up() == -(-x).next_down()` holds for all `x`. When `x` + /// is finite `x == x.next_up().next_down()` also holds. + /// + /// ```rust + /// #![feature(float_next_up_down)] + /// // f64::EPSILON is the difference between 1.0 and the next number up. + /// assert_eq!(1.0f64.next_up(), 1.0 + f64::EPSILON); + /// // But not for most numbers. + /// assert!(0.1f64.next_up() < 0.1 + f64::EPSILON); + /// assert_eq!(9007199254740992f64.next_up(), 9007199254740994.0); + /// ``` + /// + /// [`NEG_INFINITY`]: Self::NEG_INFINITY + /// [`INFINITY`]: Self::INFINITY + /// [`MIN`]: Self::MIN + /// [`MAX`]: Self::MAX + #[unstable(feature = "float_next_up_down", issue = "none")] + pub const fn next_up(self) -> Self { + // We must use strictly integer arithmetic to prevent denormals from + // flushing to zero after an arithmetic operation on some platforms. + const TINY_BITS: u64 = 0x1; // Smallest positive f64. + const CLEAR_SIGN_MASK: u64 = 0x7fff_ffff_ffff_ffff; + + let bits = self.to_bits(); + if self.is_nan() || bits == Self::INFINITY.to_bits() { + return self; + } + + let abs = bits & CLEAR_SIGN_MASK; + let next_bits = if abs == 0 { + TINY_BITS + } else if bits == abs { + bits + 1 + } else { + bits - 1 + }; + Self::from_bits(next_bits) + } + + /// Returns the greatest number less than `self`. + /// + /// Let `TINY` be the smallest representable positive `f64`. Then, + /// - if `self.is_nan()`, this returns `self`; + /// - if `self` is [`INFINITY`], this returns [`MAX`]; + /// - if `self` is `TINY`, this returns 0.0; + /// - if `self` is -0.0 or +0.0, this returns `-TINY`; + /// - if `self` is [`MIN`] or [`NEG_INFINITY`], this returns [`NEG_INFINITY`]; + /// - otherwise the unique greatest value less than `self` is returned. + /// + /// The identity `x.next_down() == -(-x).next_up()` holds for all `x`. When `x` + /// is finite `x == x.next_down().next_up()` also holds. + /// + /// ```rust + /// #![feature(float_next_up_down)] + /// let x = 1.0f64; + /// // Clamp value into range [0, 1). + /// let clamped = x.clamp(0.0, 1.0f64.next_down()); + /// assert!(clamped < 1.0); + /// assert_eq!(clamped.next_up(), 1.0); + /// ``` + /// + /// [`NEG_INFINITY`]: Self::NEG_INFINITY + /// [`INFINITY`]: Self::INFINITY + /// [`MIN`]: Self::MIN + /// [`MAX`]: Self::MAX + #[unstable(feature = "float_next_up_down", issue = "none")] + pub const fn next_down(self) -> Self { + // We must use strictly integer arithmetic to prevent denormals from + // flushing to zero after an arithmetic operation on some platforms. + const NEG_TINY_BITS: u64 = 0x8000_0000_0000_0001; // Smallest (in magnitude) negative f64. + const CLEAR_SIGN_MASK: u64 = 0x7fff_ffff_ffff_ffff; + + let bits = self.to_bits(); + if self.is_nan() || bits == Self::NEG_INFINITY.to_bits() { + return self; + } + + let abs = bits & CLEAR_SIGN_MASK; + let next_bits = if abs == 0 { + NEG_TINY_BITS + } else if bits == abs { + bits - 1 + } else { + bits + 1 + }; + Self::from_bits(next_bits) + } + /// Takes the reciprocal (inverse) of a number, `1/x`. /// /// ``` diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs index 69fa203ff4e..19de0cf6c75 100644 --- a/library/std/src/f32/tests.rs +++ b/library/std/src/f32/tests.rs @@ -299,6 +299,69 @@ fn test_is_sign_negative() { assert!((-f32::NAN).is_sign_negative()); } +#[test] +fn test_next_up() { + let tiny = f32::from_bits(1); + let tiny_up = f32::from_bits(2); + let max_down = f32::from_bits(0x7f7f_fffe); + let largest_subnormal = f32::from_bits(0x007f_ffff); + let smallest_normal = f32::from_bits(0x0080_0000); + + // Check that NaNs roundtrip. + let nan0 = f32::NAN.to_bits(); + let nan1 = f32::NAN.to_bits() ^ 0x002a_aaaa; + let nan2 = f32::NAN.to_bits() ^ 0x0055_5555; + assert_eq!(f32::from_bits(nan0).next_up().to_bits(), nan0); + assert_eq!(f32::from_bits(nan1).next_up().to_bits(), nan1); + assert_eq!(f32::from_bits(nan2).next_up().to_bits(), nan2); + + assert_eq!(f32::NEG_INFINITY.next_up(), f32::MIN); + assert_eq!(f32::MIN.next_up(), -max_down); + assert_eq!((-1.0 - f32::EPSILON).next_up(), -1.0); + assert_eq!((-smallest_normal).next_up(), -largest_subnormal); + assert_eq!((-tiny_up).next_up(), -tiny); + assert_eq!((-tiny).next_up().to_bits(), (-0.0f32).to_bits()); + assert_eq!((-0.0f32).next_up(), tiny); + assert_eq!(0.0f32.next_up(), tiny); + assert_eq!(tiny.next_up(), tiny_up); + assert_eq!(largest_subnormal.next_up(), smallest_normal); + assert_eq!(1.0f32.next_up(), 1.0 + f32::EPSILON); + assert_eq!(f32::MAX.next_up(), f32::INFINITY); + assert_eq!(f32::INFINITY.next_up(), f32::INFINITY); +} + +#[test] +fn test_next_down() { + let tiny = f32::from_bits(1); + let tiny_up = f32::from_bits(2); + let max_down = f32::from_bits(0x7f7f_fffe); + let largest_subnormal = f32::from_bits(0x007f_ffff); + let smallest_normal = f32::from_bits(0x0080_0000); + + // Check that NaNs roundtrip. + let nan0 = f32::NAN.to_bits(); + let nan1 = f32::NAN.to_bits() ^ 0x002a_aaaa; + let nan2 = f32::NAN.to_bits() ^ 0x0055_5555; + assert_eq!(f32::from_bits(nan0).next_down().to_bits(), nan0); + assert_eq!(f32::from_bits(nan1).next_down().to_bits(), nan1); + assert_eq!(f32::from_bits(nan2).next_down().to_bits(), nan2); + + assert_eq!(f32::NEG_INFINITY.next_down(), f32::NEG_INFINITY); + assert_eq!(f32::MIN.next_down(), f32::NEG_INFINITY); + assert_eq!((-max_down).next_down(), f32::MIN); + assert_eq!((-1.0f32).next_down(), -1.0 - f32::EPSILON); + assert_eq!((-largest_subnormal).next_down(), -smallest_normal); + assert_eq!((-tiny).next_down(), -tiny_up); + assert_eq!((-0.0f32).next_down(), -tiny); + assert_eq!((0.0f32).next_down(), -tiny); + assert_eq!(tiny.next_down().to_bits(), 0.0f32.to_bits()); + assert_eq!(tiny_up.next_down(), tiny); + assert_eq!(smallest_normal.next_down(), largest_subnormal); + assert_eq!((1.0 + f32::EPSILON).next_down(), 1.0f32); + assert_eq!(f32::MAX.next_down(), max_down); + assert_eq!(f32::INFINITY.next_down(), f32::MAX); +} + #[test] fn test_mul_add() { let nan: f32 = f32::NAN; diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs index 5c163cfe90e..8e172cf4963 100644 --- a/library/std/src/f64/tests.rs +++ b/library/std/src/f64/tests.rs @@ -289,6 +289,69 @@ fn test_is_sign_negative() { assert!((-f64::NAN).is_sign_negative()); } +#[test] +fn test_next_up() { + let tiny = f64::from_bits(1); + let tiny_up = f64::from_bits(2); + let max_down = f64::from_bits(0x7fef_ffff_ffff_fffe); + let largest_subnormal = f64::from_bits(0x000f_ffff_ffff_ffff); + let smallest_normal = f64::from_bits(0x0010_0000_0000_0000); + + // Check that NaNs roundtrip. + let nan0 = f64::NAN.to_bits(); + let nan1 = f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa; + let nan2 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555; + assert_eq!(f64::from_bits(nan0).next_up().to_bits(), nan0); + assert_eq!(f64::from_bits(nan1).next_up().to_bits(), nan1); + assert_eq!(f64::from_bits(nan2).next_up().to_bits(), nan2); + + assert_eq!(f64::NEG_INFINITY.next_up(), f64::MIN); + assert_eq!(f64::MIN.next_up(), -max_down); + assert_eq!((-1.0 - f64::EPSILON).next_up(), -1.0); + assert_eq!((-smallest_normal).next_up(), -largest_subnormal); + assert_eq!((-tiny_up).next_up(), -tiny); + assert_eq!((-tiny).next_up().to_bits(), (-0.0f64).to_bits()); + assert_eq!((-0.0f64).next_up(), tiny); + assert_eq!(0.0f64.next_up(), tiny); + assert_eq!(tiny.next_up(), tiny_up); + assert_eq!(largest_subnormal.next_up(), smallest_normal); + assert_eq!(1.0f64.next_up(), 1.0 + f64::EPSILON); + assert_eq!(f64::MAX.next_up(), f64::INFINITY); + assert_eq!(f64::INFINITY.next_up(), f64::INFINITY); +} + +#[test] +fn test_next_down() { + let tiny = f64::from_bits(1); + let tiny_up = f64::from_bits(2); + let max_down = f64::from_bits(0x7fef_ffff_ffff_fffe); + let largest_subnormal = f64::from_bits(0x000f_ffff_ffff_ffff); + let smallest_normal = f64::from_bits(0x0010_0000_0000_0000); + + // Check that NaNs roundtrip. + let nan0 = f64::NAN.to_bits(); + let nan1 = f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa; + let nan2 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555; + assert_eq!(f64::from_bits(nan0).next_down().to_bits(), nan0); + assert_eq!(f64::from_bits(nan1).next_down().to_bits(), nan1); + assert_eq!(f64::from_bits(nan2).next_down().to_bits(), nan2); + + assert_eq!(f64::NEG_INFINITY.next_down(), f64::NEG_INFINITY); + assert_eq!(f64::MIN.next_down(), f64::NEG_INFINITY); + assert_eq!((-max_down).next_down(), f64::MIN); + assert_eq!((-1.0f64).next_down(), -1.0 - f64::EPSILON); + assert_eq!((-largest_subnormal).next_down(), -smallest_normal); + assert_eq!((-tiny).next_down(), -tiny_up); + assert_eq!((-0.0f64).next_down(), -tiny); + assert_eq!((0.0f64).next_down(), -tiny); + assert_eq!(tiny.next_down().to_bits(), 0.0f64.to_bits()); + assert_eq!(tiny_up.next_down(), tiny); + assert_eq!(smallest_normal.next_down(), largest_subnormal); + assert_eq!((1.0 + f64::EPSILON).next_down(), 1.0f64); + assert_eq!(f64::MAX.next_down(), max_down); + assert_eq!(f64::INFINITY.next_down(), f64::MAX); +} + #[test] fn test_mul_add() { let nan: f64 = f64::NAN; diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 475a1d9fd99..e0473f746e5 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -273,6 +273,7 @@ #![feature(exclusive_wrapper)] #![feature(extend_one)] #![feature(float_minimum_maximum)] +#![feature(float_next_up_down)] #![feature(hasher_prefixfree_extras)] #![feature(hashmap_internals)] #![feature(int_error_internals)] -- cgit 1.4.1-3-g733a5 From 3241bbcbc792c0391ed8ed2772ba02b4c9cae67d Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Sat, 30 Oct 2021 09:25:04 +0200 Subject: Fixed float next_up/down 32-bit x87 float NaN roundtrip test case. --- library/std/src/f32/tests.rs | 24 ++++++++++++------------ library/std/src/f64/tests.rs | 24 ++++++++++++------------ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs index 19de0cf6c75..07b9ff3a789 100644 --- a/library/std/src/f32/tests.rs +++ b/library/std/src/f32/tests.rs @@ -308,12 +308,12 @@ fn test_next_up() { let smallest_normal = f32::from_bits(0x0080_0000); // Check that NaNs roundtrip. - let nan0 = f32::NAN.to_bits(); - let nan1 = f32::NAN.to_bits() ^ 0x002a_aaaa; - let nan2 = f32::NAN.to_bits() ^ 0x0055_5555; - assert_eq!(f32::from_bits(nan0).next_up().to_bits(), nan0); - assert_eq!(f32::from_bits(nan1).next_up().to_bits(), nan1); - assert_eq!(f32::from_bits(nan2).next_up().to_bits(), nan2); + let nan0 = f32::NAN; + let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa); + let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555); + assert_eq!(nan0.next_up().to_bits(), nan0.to_bits()); + assert_eq!(nan1.next_up().to_bits(), nan1.to_bits()); + assert_eq!(nan2.next_up().to_bits(), nan2.to_bits()); assert_eq!(f32::NEG_INFINITY.next_up(), f32::MIN); assert_eq!(f32::MIN.next_up(), -max_down); @@ -339,12 +339,12 @@ fn test_next_down() { let smallest_normal = f32::from_bits(0x0080_0000); // Check that NaNs roundtrip. - let nan0 = f32::NAN.to_bits(); - let nan1 = f32::NAN.to_bits() ^ 0x002a_aaaa; - let nan2 = f32::NAN.to_bits() ^ 0x0055_5555; - assert_eq!(f32::from_bits(nan0).next_down().to_bits(), nan0); - assert_eq!(f32::from_bits(nan1).next_down().to_bits(), nan1); - assert_eq!(f32::from_bits(nan2).next_down().to_bits(), nan2); + let nan0 = f32::NAN; + let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa); + let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555); + assert_eq!(nan0.next_down().to_bits(), nan0.to_bits()); + assert_eq!(nan1.next_down().to_bits(), nan1.to_bits()); + assert_eq!(nan2.next_down().to_bits(), nan2.to_bits()); assert_eq!(f32::NEG_INFINITY.next_down(), f32::NEG_INFINITY); assert_eq!(f32::MIN.next_down(), f32::NEG_INFINITY); diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs index 8e172cf4963..cf46ffcffcf 100644 --- a/library/std/src/f64/tests.rs +++ b/library/std/src/f64/tests.rs @@ -298,12 +298,12 @@ fn test_next_up() { let smallest_normal = f64::from_bits(0x0010_0000_0000_0000); // Check that NaNs roundtrip. - let nan0 = f64::NAN.to_bits(); - let nan1 = f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa; - let nan2 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555; - assert_eq!(f64::from_bits(nan0).next_up().to_bits(), nan0); - assert_eq!(f64::from_bits(nan1).next_up().to_bits(), nan1); - assert_eq!(f64::from_bits(nan2).next_up().to_bits(), nan2); + let nan0 = f64::NAN; + let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa); + let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555); + assert_eq!(nan0.next_up().to_bits(), nan0.to_bits()); + assert_eq!(nan1.next_up().to_bits(), nan1.to_bits()); + assert_eq!(nan2.next_up().to_bits(), nan2.to_bits()); assert_eq!(f64::NEG_INFINITY.next_up(), f64::MIN); assert_eq!(f64::MIN.next_up(), -max_down); @@ -329,12 +329,12 @@ fn test_next_down() { let smallest_normal = f64::from_bits(0x0010_0000_0000_0000); // Check that NaNs roundtrip. - let nan0 = f64::NAN.to_bits(); - let nan1 = f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa; - let nan2 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555; - assert_eq!(f64::from_bits(nan0).next_down().to_bits(), nan0); - assert_eq!(f64::from_bits(nan1).next_down().to_bits(), nan1); - assert_eq!(f64::from_bits(nan2).next_down().to_bits(), nan2); + let nan0 = f64::NAN; + let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa); + let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555); + assert_eq!(nan0.next_down().to_bits(), nan0.to_bits()); + assert_eq!(nan1.next_down().to_bits(), nan1.to_bits()); + assert_eq!(nan2.next_down().to_bits(), nan2.to_bits()); assert_eq!(f64::NEG_INFINITY.next_down(), f64::NEG_INFINITY); assert_eq!(f64::MIN.next_down(), f64::NEG_INFINITY); -- cgit 1.4.1-3-g733a5 From de757e8a98ce0a4efe91f2f46e93abe1c197bcdf Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Mon, 29 Nov 2021 12:10:09 +0100 Subject: Ensure NaN references values go through function boundary for next_up/down. --- library/std/src/f32/tests.rs | 24 ++++++++++++++++++------ library/std/src/f64/tests.rs | 24 ++++++++++++++++++------ 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs index 07b9ff3a789..7a2f9bd4878 100644 --- a/library/std/src/f32/tests.rs +++ b/library/std/src/f32/tests.rs @@ -308,12 +308,18 @@ fn test_next_up() { let smallest_normal = f32::from_bits(0x0080_0000); // Check that NaNs roundtrip. + // Because x87 can lose NaN bits when passed through a function, ensure the reference value + // also passes through a function boundary. + #[inline(never)] + fn identity(x: f32) -> f32 { + crate::hint::black_box(x) + } let nan0 = f32::NAN; let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa); let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555); - assert_eq!(nan0.next_up().to_bits(), nan0.to_bits()); - assert_eq!(nan1.next_up().to_bits(), nan1.to_bits()); - assert_eq!(nan2.next_up().to_bits(), nan2.to_bits()); + assert_eq!(nan0.next_up().to_bits(), identity(nan0).to_bits()); + assert_eq!(nan1.next_up().to_bits(), identity(nan1).to_bits()); + assert_eq!(nan2.next_up().to_bits(), identity(nan2).to_bits()); assert_eq!(f32::NEG_INFINITY.next_up(), f32::MIN); assert_eq!(f32::MIN.next_up(), -max_down); @@ -339,12 +345,18 @@ fn test_next_down() { let smallest_normal = f32::from_bits(0x0080_0000); // Check that NaNs roundtrip. + // Because x87 can lose NaN bits when passed through a function, ensure the reference value + // also passes through a function boundary. + #[inline(never)] + fn identity(x: f32) -> f32 { + crate::hint::black_box(x) + } let nan0 = f32::NAN; let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa); let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555); - assert_eq!(nan0.next_down().to_bits(), nan0.to_bits()); - assert_eq!(nan1.next_down().to_bits(), nan1.to_bits()); - assert_eq!(nan2.next_down().to_bits(), nan2.to_bits()); + assert_eq!(nan0.next_down().to_bits(), identity(nan0).to_bits()); + assert_eq!(nan1.next_down().to_bits(), identity(nan1).to_bits()); + assert_eq!(nan2.next_down().to_bits(), identity(nan2).to_bits()); assert_eq!(f32::NEG_INFINITY.next_down(), f32::NEG_INFINITY); assert_eq!(f32::MIN.next_down(), f32::NEG_INFINITY); diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs index cf46ffcffcf..2524bfe8b99 100644 --- a/library/std/src/f64/tests.rs +++ b/library/std/src/f64/tests.rs @@ -298,12 +298,18 @@ fn test_next_up() { let smallest_normal = f64::from_bits(0x0010_0000_0000_0000); // Check that NaNs roundtrip. + // Because x87 can lose NaN bits when passed through a function, ensure the reference value + // also passes through a function boundary. + #[inline(never)] + fn identity(x: f64) -> f64 { + crate::hint::black_box(x) + } let nan0 = f64::NAN; let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa); let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555); - assert_eq!(nan0.next_up().to_bits(), nan0.to_bits()); - assert_eq!(nan1.next_up().to_bits(), nan1.to_bits()); - assert_eq!(nan2.next_up().to_bits(), nan2.to_bits()); + assert_eq!(nan0.next_up().to_bits(), identity(nan0).to_bits()); + assert_eq!(nan1.next_up().to_bits(), identity(nan1).to_bits()); + assert_eq!(nan2.next_up().to_bits(), identity(nan2).to_bits()); assert_eq!(f64::NEG_INFINITY.next_up(), f64::MIN); assert_eq!(f64::MIN.next_up(), -max_down); @@ -329,12 +335,18 @@ fn test_next_down() { let smallest_normal = f64::from_bits(0x0010_0000_0000_0000); // Check that NaNs roundtrip. + // Because x87 can lose NaN bits when passed through a function, ensure the reference value + // also passes through a function boundary. + #[inline(never)] + fn identity(x: f64) -> f64 { + crate::hint::black_box(x) + } let nan0 = f64::NAN; let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa); let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555); - assert_eq!(nan0.next_down().to_bits(), nan0.to_bits()); - assert_eq!(nan1.next_down().to_bits(), nan1.to_bits()); - assert_eq!(nan2.next_down().to_bits(), nan2.to_bits()); + assert_eq!(nan0.next_down().to_bits(), identity(nan0).to_bits()); + assert_eq!(nan1.next_down().to_bits(), identity(nan1).to_bits()); + assert_eq!(nan2.next_down().to_bits(), identity(nan2).to_bits()); assert_eq!(f64::NEG_INFINITY.next_down(), f64::NEG_INFINITY); assert_eq!(f64::MIN.next_down(), f64::NEG_INFINITY); -- cgit 1.4.1-3-g733a5 From 712bf2a07a31f1fb8234ec5823d9913f1091e413 Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Tue, 30 Nov 2021 20:54:12 +0100 Subject: Added tracking issue numbers for float_next_up_down. --- library/core/src/num/f32.rs | 6 ++++-- library/core/src/num/f64.rs | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 7c38d830636..f6cef3f8067 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -704,7 +704,8 @@ impl f32 { /// [`INFINITY`]: Self::INFINITY /// [`MIN`]: Self::MIN /// [`MAX`]: Self::MAX - #[unstable(feature = "float_next_up_down", issue = "none")] + #[unstable(feature = "float_next_up_down", issue = "91399")] + #[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")] pub const fn next_up(self) -> Self { // We must use strictly integer arithmetic to prevent denormals from // flushing to zero after an arithmetic operation on some platforms. @@ -753,7 +754,8 @@ impl f32 { /// [`INFINITY`]: Self::INFINITY /// [`MIN`]: Self::MIN /// [`MAX`]: Self::MAX - #[unstable(feature = "float_next_up_down", issue = "none")] + #[unstable(feature = "float_next_up_down", issue = "91399")] + #[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")] pub const fn next_down(self) -> Self { // We must use strictly integer arithmetic to prevent denormals from // flushing to zero after an arithmetic operation on some platforms. diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 8146f007531..328b19b203c 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -714,7 +714,8 @@ impl f64 { /// [`INFINITY`]: Self::INFINITY /// [`MIN`]: Self::MIN /// [`MAX`]: Self::MAX - #[unstable(feature = "float_next_up_down", issue = "none")] + #[unstable(feature = "float_next_up_down", issue = "91399")] + #[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")] pub const fn next_up(self) -> Self { // We must use strictly integer arithmetic to prevent denormals from // flushing to zero after an arithmetic operation on some platforms. @@ -763,7 +764,8 @@ impl f64 { /// [`INFINITY`]: Self::INFINITY /// [`MIN`]: Self::MIN /// [`MAX`]: Self::MAX - #[unstable(feature = "float_next_up_down", issue = "none")] + #[unstable(feature = "float_next_up_down", issue = "91399")] + #[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")] pub const fn next_down(self) -> Self { // We must use strictly integer arithmetic to prevent denormals from // flushing to zero after an arithmetic operation on some platforms. -- cgit 1.4.1-3-g733a5 From fbe215af53da287dc220f319543a5ef4e75f6c54 Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Tue, 30 Nov 2021 21:08:37 +0100 Subject: Conditionally do not compile NaN roundtrip tests on x87 fp. --- library/std/src/f32/tests.rs | 44 ++++++++++++++++++++++---------------------- library/std/src/f64/tests.rs | 44 ++++++++++++++++++++++---------------------- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs index 7a2f9bd4878..4fb9f73ef37 100644 --- a/library/std/src/f32/tests.rs +++ b/library/std/src/f32/tests.rs @@ -308,18 +308,18 @@ fn test_next_up() { let smallest_normal = f32::from_bits(0x0080_0000); // Check that NaNs roundtrip. - // Because x87 can lose NaN bits when passed through a function, ensure the reference value - // also passes through a function boundary. - #[inline(never)] - fn identity(x: f32) -> f32 { - crate::hint::black_box(x) + // Ignore test on x87 floating point, the code is still correct but these + // platforms do not guarantee NaN payloads are preserved, which caused these + // tests to fail. + #[cfg(not(all(target_arch = "x86", not(target_feature = "fxsr"))))] + { + let nan0 = f32::NAN; + let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa); + let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555); + assert_eq!(nan0.next_up().to_bits(), nan0.to_bits()); + assert_eq!(nan1.next_up().to_bits(), nan1.to_bits()); + assert_eq!(nan2.next_up().to_bits(), nan2.to_bits()); } - let nan0 = f32::NAN; - let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa); - let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555); - assert_eq!(nan0.next_up().to_bits(), identity(nan0).to_bits()); - assert_eq!(nan1.next_up().to_bits(), identity(nan1).to_bits()); - assert_eq!(nan2.next_up().to_bits(), identity(nan2).to_bits()); assert_eq!(f32::NEG_INFINITY.next_up(), f32::MIN); assert_eq!(f32::MIN.next_up(), -max_down); @@ -345,18 +345,18 @@ fn test_next_down() { let smallest_normal = f32::from_bits(0x0080_0000); // Check that NaNs roundtrip. - // Because x87 can lose NaN bits when passed through a function, ensure the reference value - // also passes through a function boundary. - #[inline(never)] - fn identity(x: f32) -> f32 { - crate::hint::black_box(x) + // Ignore test on x87 floating point, the code is still correct but these + // platforms do not guarantee NaN payloads are preserved, which caused these + // tests to fail. + #[cfg(not(all(target_arch = "x86", not(target_feature = "fxsr"))))] + { + let nan0 = f32::NAN; + let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa); + let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555); + assert_eq!(nan0.next_down().to_bits(), nan0.to_bits()); + assert_eq!(nan1.next_down().to_bits(), nan1.to_bits()); + assert_eq!(nan2.next_down().to_bits(), nan2.to_bits()); } - let nan0 = f32::NAN; - let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa); - let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555); - assert_eq!(nan0.next_down().to_bits(), identity(nan0).to_bits()); - assert_eq!(nan1.next_down().to_bits(), identity(nan1).to_bits()); - assert_eq!(nan2.next_down().to_bits(), identity(nan2).to_bits()); assert_eq!(f32::NEG_INFINITY.next_down(), f32::NEG_INFINITY); assert_eq!(f32::MIN.next_down(), f32::NEG_INFINITY); diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs index 2524bfe8b99..e545a10c489 100644 --- a/library/std/src/f64/tests.rs +++ b/library/std/src/f64/tests.rs @@ -298,18 +298,18 @@ fn test_next_up() { let smallest_normal = f64::from_bits(0x0010_0000_0000_0000); // Check that NaNs roundtrip. - // Because x87 can lose NaN bits when passed through a function, ensure the reference value - // also passes through a function boundary. - #[inline(never)] - fn identity(x: f64) -> f64 { - crate::hint::black_box(x) + // Ignore test on x87 floating point, the code is still correct but these + // platforms do not guarantee NaN payloads are preserved, which caused these + // tests to fail. + #[cfg(not(all(target_arch = "x86", not(target_feature = "fxsr"))))] + { + let nan0 = f64::NAN; + let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa); + let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555); + assert_eq!(nan0.next_up().to_bits(), nan0.to_bits()); + assert_eq!(nan1.next_up().to_bits(), nan1.to_bits()); + assert_eq!(nan2.next_up().to_bits(), nan2.to_bits()); } - let nan0 = f64::NAN; - let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa); - let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555); - assert_eq!(nan0.next_up().to_bits(), identity(nan0).to_bits()); - assert_eq!(nan1.next_up().to_bits(), identity(nan1).to_bits()); - assert_eq!(nan2.next_up().to_bits(), identity(nan2).to_bits()); assert_eq!(f64::NEG_INFINITY.next_up(), f64::MIN); assert_eq!(f64::MIN.next_up(), -max_down); @@ -335,18 +335,18 @@ fn test_next_down() { let smallest_normal = f64::from_bits(0x0010_0000_0000_0000); // Check that NaNs roundtrip. - // Because x87 can lose NaN bits when passed through a function, ensure the reference value - // also passes through a function boundary. - #[inline(never)] - fn identity(x: f64) -> f64 { - crate::hint::black_box(x) + // Ignore test on x87 floating point, the code is still correct but these + // platforms do not guarantee NaN payloads are preserved, which caused these + // tests to fail. + #[cfg(not(all(target_arch = "x86", not(target_feature = "fxsr"))))] + { + let nan0 = f64::NAN; + let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa); + let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555); + assert_eq!(nan0.next_down().to_bits(), nan0.to_bits()); + assert_eq!(nan1.next_down().to_bits(), nan1.to_bits()); + assert_eq!(nan2.next_down().to_bits(), nan2.to_bits()); } - let nan0 = f64::NAN; - let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa); - let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555); - assert_eq!(nan0.next_down().to_bits(), identity(nan0).to_bits()); - assert_eq!(nan1.next_down().to_bits(), identity(nan1).to_bits()); - assert_eq!(nan2.next_down().to_bits(), identity(nan2).to_bits()); assert_eq!(f64::NEG_INFINITY.next_down(), f64::NEG_INFINITY); assert_eq!(f64::MIN.next_down(), f64::NEG_INFINITY); -- cgit 1.4.1-3-g733a5 From 18d61bfbf45f2e1cef44dce832cfe69feb76d13f Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Sat, 19 Feb 2022 11:22:27 +0100 Subject: Skip next_up/down tests entirely on x87. --- library/std/src/f32/tests.rs | 108 ++++++++++++++++++++------------------- library/std/src/f64/tests.rs | 118 +++++++++++++++++++++---------------------- 2 files changed, 114 insertions(+), 112 deletions(-) diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs index 4fb9f73ef37..0e2f0561ea0 100644 --- a/library/std/src/f32/tests.rs +++ b/library/std/src/f32/tests.rs @@ -299,6 +299,19 @@ fn test_is_sign_negative() { assert!((-f32::NAN).is_sign_negative()); } +macro_rules! assert_f32_biteq { + ($left : expr, $right : expr) => { + let l: &f32 = &$left; + let r: &f32 = &$right; + let lb = l.to_bits(); + let rb = r.to_bits(); + assert_eq!(lb, rb, "float {} ({:#x}) is not equal to {} ({:#x})", *l, lb, *r, rb); + } +} + +// Ignore test on x87 floating point, these platforms do not guarantee NaN +// payloads are preserved and flush denormals to zero, failing the tests. +#[cfg(not(target_arch = "x86"))] #[test] fn test_next_up() { let tiny = f32::from_bits(1); @@ -306,36 +319,32 @@ fn test_next_up() { let max_down = f32::from_bits(0x7f7f_fffe); let largest_subnormal = f32::from_bits(0x007f_ffff); let smallest_normal = f32::from_bits(0x0080_0000); + assert_f32_biteq!(f32::NEG_INFINITY.next_up(), f32::MIN); + assert_f32_biteq!(f32::MIN.next_up(), -max_down); + assert_f32_biteq!((-1.0 - f32::EPSILON).next_up(), -1.0); + assert_f32_biteq!((-smallest_normal).next_up(), -largest_subnormal); + assert_f32_biteq!((-tiny_up).next_up(), -tiny); + assert_f32_biteq!((-tiny).next_up(), -0.0f32); + assert_f32_biteq!((-0.0f32).next_up(), tiny); + assert_f32_biteq!(0.0f32.next_up(), tiny); + assert_f32_biteq!(tiny.next_up(), tiny_up); + assert_f32_biteq!(largest_subnormal.next_up(), smallest_normal); + assert_f32_biteq!(1.0f32.next_up(), 1.0 + f32::EPSILON); + assert_f32_biteq!(f32::MAX.next_up(), f32::INFINITY); + assert_f32_biteq!(f32::INFINITY.next_up(), f32::INFINITY); // Check that NaNs roundtrip. - // Ignore test on x87 floating point, the code is still correct but these - // platforms do not guarantee NaN payloads are preserved, which caused these - // tests to fail. - #[cfg(not(all(target_arch = "x86", not(target_feature = "fxsr"))))] - { - let nan0 = f32::NAN; - let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa); - let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555); - assert_eq!(nan0.next_up().to_bits(), nan0.to_bits()); - assert_eq!(nan1.next_up().to_bits(), nan1.to_bits()); - assert_eq!(nan2.next_up().to_bits(), nan2.to_bits()); - } - - assert_eq!(f32::NEG_INFINITY.next_up(), f32::MIN); - assert_eq!(f32::MIN.next_up(), -max_down); - assert_eq!((-1.0 - f32::EPSILON).next_up(), -1.0); - assert_eq!((-smallest_normal).next_up(), -largest_subnormal); - assert_eq!((-tiny_up).next_up(), -tiny); - assert_eq!((-tiny).next_up().to_bits(), (-0.0f32).to_bits()); - assert_eq!((-0.0f32).next_up(), tiny); - assert_eq!(0.0f32.next_up(), tiny); - assert_eq!(tiny.next_up(), tiny_up); - assert_eq!(largest_subnormal.next_up(), smallest_normal); - assert_eq!(1.0f32.next_up(), 1.0 + f32::EPSILON); - assert_eq!(f32::MAX.next_up(), f32::INFINITY); - assert_eq!(f32::INFINITY.next_up(), f32::INFINITY); + let nan0 = f32::NAN; + let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa); + let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555); + assert_f32_biteq!(nan0.next_up(), nan0); + assert_f32_biteq!(nan1.next_up(), nan1); + assert_f32_biteq!(nan2.next_up(), nan2); } +// Ignore test on x87 floating point, these platforms do not guarantee NaN +// payloads are preserved and flush denormals to zero, failing the tests. +#[cfg(not(target_arch = "x86"))] #[test] fn test_next_down() { let tiny = f32::from_bits(1); @@ -343,35 +352,28 @@ fn test_next_down() { let max_down = f32::from_bits(0x7f7f_fffe); let largest_subnormal = f32::from_bits(0x007f_ffff); let smallest_normal = f32::from_bits(0x0080_0000); + assert_f32_biteq!(f32::NEG_INFINITY.next_down(), f32::NEG_INFINITY); + assert_f32_biteq!(f32::MIN.next_down(), f32::NEG_INFINITY); + assert_f32_biteq!((-max_down).next_down(), f32::MIN); + assert_f32_biteq!((-1.0f32).next_down(), -1.0 - f32::EPSILON); + assert_f32_biteq!((-largest_subnormal).next_down(), -smallest_normal); + assert_f32_biteq!((-tiny).next_down(), -tiny_up); + assert_f32_biteq!((-0.0f32).next_down(), -tiny); + assert_f32_biteq!((0.0f32).next_down(), -tiny); + assert_f32_biteq!(tiny.next_down(), 0.0f32); + assert_f32_biteq!(tiny_up.next_down(), tiny); + assert_f32_biteq!(smallest_normal.next_down(), largest_subnormal); + assert_f32_biteq!((1.0 + f32::EPSILON).next_down(), 1.0f32); + assert_f32_biteq!(f32::MAX.next_down(), max_down); + assert_f32_biteq!(f32::INFINITY.next_down(), f32::MAX); // Check that NaNs roundtrip. - // Ignore test on x87 floating point, the code is still correct but these - // platforms do not guarantee NaN payloads are preserved, which caused these - // tests to fail. - #[cfg(not(all(target_arch = "x86", not(target_feature = "fxsr"))))] - { - let nan0 = f32::NAN; - let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa); - let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555); - assert_eq!(nan0.next_down().to_bits(), nan0.to_bits()); - assert_eq!(nan1.next_down().to_bits(), nan1.to_bits()); - assert_eq!(nan2.next_down().to_bits(), nan2.to_bits()); - } - - assert_eq!(f32::NEG_INFINITY.next_down(), f32::NEG_INFINITY); - assert_eq!(f32::MIN.next_down(), f32::NEG_INFINITY); - assert_eq!((-max_down).next_down(), f32::MIN); - assert_eq!((-1.0f32).next_down(), -1.0 - f32::EPSILON); - assert_eq!((-largest_subnormal).next_down(), -smallest_normal); - assert_eq!((-tiny).next_down(), -tiny_up); - assert_eq!((-0.0f32).next_down(), -tiny); - assert_eq!((0.0f32).next_down(), -tiny); - assert_eq!(tiny.next_down().to_bits(), 0.0f32.to_bits()); - assert_eq!(tiny_up.next_down(), tiny); - assert_eq!(smallest_normal.next_down(), largest_subnormal); - assert_eq!((1.0 + f32::EPSILON).next_down(), 1.0f32); - assert_eq!(f32::MAX.next_down(), max_down); - assert_eq!(f32::INFINITY.next_down(), f32::MAX); + let nan0 = f32::NAN; + let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa); + let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555); + assert_f32_biteq!(nan0.next_down(), nan0); + assert_f32_biteq!(nan1.next_down(), nan1); + assert_f32_biteq!(nan2.next_down(), nan2); } #[test] diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs index e545a10c489..8125b249227 100644 --- a/library/std/src/f64/tests.rs +++ b/library/std/src/f64/tests.rs @@ -289,6 +289,19 @@ fn test_is_sign_negative() { assert!((-f64::NAN).is_sign_negative()); } +macro_rules! assert_f64_biteq { + ($left : expr, $right : expr) => { + let l: &f64 = &$left; + let r: &f64 = &$right; + let lb = l.to_bits(); + let rb = r.to_bits(); + assert_eq!(lb, rb, "float {} ({:#x}) is not equal to {} ({:#x})", *l, lb, *r, rb); + } +} + +// Ignore test on x87 floating point, these platforms do not guarantee NaN +// payloads are preserved and flush denormals to zero, failing the tests. +#[cfg(not(target_arch = "x86"))] #[test] fn test_next_up() { let tiny = f64::from_bits(1); @@ -296,36 +309,31 @@ fn test_next_up() { let max_down = f64::from_bits(0x7fef_ffff_ffff_fffe); let largest_subnormal = f64::from_bits(0x000f_ffff_ffff_ffff); let smallest_normal = f64::from_bits(0x0010_0000_0000_0000); - - // Check that NaNs roundtrip. - // Ignore test on x87 floating point, the code is still correct but these - // platforms do not guarantee NaN payloads are preserved, which caused these - // tests to fail. - #[cfg(not(all(target_arch = "x86", not(target_feature = "fxsr"))))] - { - let nan0 = f64::NAN; - let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa); - let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555); - assert_eq!(nan0.next_up().to_bits(), nan0.to_bits()); - assert_eq!(nan1.next_up().to_bits(), nan1.to_bits()); - assert_eq!(nan2.next_up().to_bits(), nan2.to_bits()); - } - - assert_eq!(f64::NEG_INFINITY.next_up(), f64::MIN); - assert_eq!(f64::MIN.next_up(), -max_down); - assert_eq!((-1.0 - f64::EPSILON).next_up(), -1.0); - assert_eq!((-smallest_normal).next_up(), -largest_subnormal); - assert_eq!((-tiny_up).next_up(), -tiny); - assert_eq!((-tiny).next_up().to_bits(), (-0.0f64).to_bits()); - assert_eq!((-0.0f64).next_up(), tiny); - assert_eq!(0.0f64.next_up(), tiny); - assert_eq!(tiny.next_up(), tiny_up); - assert_eq!(largest_subnormal.next_up(), smallest_normal); - assert_eq!(1.0f64.next_up(), 1.0 + f64::EPSILON); - assert_eq!(f64::MAX.next_up(), f64::INFINITY); - assert_eq!(f64::INFINITY.next_up(), f64::INFINITY); -} - + assert_f64_biteq!(f64::NEG_INFINITY.next_up(), f64::MIN); + assert_f64_biteq!(f64::MIN.next_up(), -max_down); + assert_f64_biteq!((-1.0 - f64::EPSILON).next_up(), -1.0); + assert_f64_biteq!((-smallest_normal).next_up(), -largest_subnormal); + assert_f64_biteq!((-tiny_up).next_up(), -tiny); + assert_f64_biteq!((-tiny).next_up(), -0.0f64); + assert_f64_biteq!((-0.0f64).next_up(), tiny); + assert_f64_biteq!(0.0f64.next_up(), tiny); + assert_f64_biteq!(tiny.next_up(), tiny_up); + assert_f64_biteq!(largest_subnormal.next_up(), smallest_normal); + assert_f64_biteq!(1.0f64.next_up(), 1.0 + f64::EPSILON); + assert_f64_biteq!(f64::MAX.next_up(), f64::INFINITY); + assert_f64_biteq!(f64::INFINITY.next_up(), f64::INFINITY); + + let nan0 = f64::NAN; + let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa); + let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555); + assert_f64_biteq!(nan0.next_up(), nan0); + assert_f64_biteq!(nan1.next_up(), nan1); + assert_f64_biteq!(nan2.next_up(), nan2); +} + +// Ignore test on x87 floating point, these platforms do not guarantee NaN +// payloads are preserved and flush denormals to zero, failing the tests. +#[cfg(not(target_arch = "x86"))] #[test] fn test_next_down() { let tiny = f64::from_bits(1); @@ -333,35 +341,27 @@ fn test_next_down() { let max_down = f64::from_bits(0x7fef_ffff_ffff_fffe); let largest_subnormal = f64::from_bits(0x000f_ffff_ffff_ffff); let smallest_normal = f64::from_bits(0x0010_0000_0000_0000); - - // Check that NaNs roundtrip. - // Ignore test on x87 floating point, the code is still correct but these - // platforms do not guarantee NaN payloads are preserved, which caused these - // tests to fail. - #[cfg(not(all(target_arch = "x86", not(target_feature = "fxsr"))))] - { - let nan0 = f64::NAN; - let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa); - let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555); - assert_eq!(nan0.next_down().to_bits(), nan0.to_bits()); - assert_eq!(nan1.next_down().to_bits(), nan1.to_bits()); - assert_eq!(nan2.next_down().to_bits(), nan2.to_bits()); - } - - assert_eq!(f64::NEG_INFINITY.next_down(), f64::NEG_INFINITY); - assert_eq!(f64::MIN.next_down(), f64::NEG_INFINITY); - assert_eq!((-max_down).next_down(), f64::MIN); - assert_eq!((-1.0f64).next_down(), -1.0 - f64::EPSILON); - assert_eq!((-largest_subnormal).next_down(), -smallest_normal); - assert_eq!((-tiny).next_down(), -tiny_up); - assert_eq!((-0.0f64).next_down(), -tiny); - assert_eq!((0.0f64).next_down(), -tiny); - assert_eq!(tiny.next_down().to_bits(), 0.0f64.to_bits()); - assert_eq!(tiny_up.next_down(), tiny); - assert_eq!(smallest_normal.next_down(), largest_subnormal); - assert_eq!((1.0 + f64::EPSILON).next_down(), 1.0f64); - assert_eq!(f64::MAX.next_down(), max_down); - assert_eq!(f64::INFINITY.next_down(), f64::MAX); + assert_f64_biteq!(f64::NEG_INFINITY.next_down(), f64::NEG_INFINITY); + assert_f64_biteq!(f64::MIN.next_down(), f64::NEG_INFINITY); + assert_f64_biteq!((-max_down).next_down(), f64::MIN); + assert_f64_biteq!((-1.0f64).next_down(), -1.0 - f64::EPSILON); + assert_f64_biteq!((-largest_subnormal).next_down(), -smallest_normal); + assert_f64_biteq!((-tiny).next_down(), -tiny_up); + assert_f64_biteq!((-0.0f64).next_down(), -tiny); + assert_f64_biteq!((0.0f64).next_down(), -tiny); + assert_f64_biteq!(tiny.next_down(), 0.0f64); + assert_f64_biteq!(tiny_up.next_down(), tiny); + assert_f64_biteq!(smallest_normal.next_down(), largest_subnormal); + assert_f64_biteq!((1.0 + f64::EPSILON).next_down(), 1.0f64); + assert_f64_biteq!(f64::MAX.next_down(), max_down); + assert_f64_biteq!(f64::INFINITY.next_down(), f64::MAX); + + let nan0 = f64::NAN; + let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa); + let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555); + assert_f64_biteq!(nan0.next_down(), nan0); + assert_f64_biteq!(nan1.next_down(), nan1); + assert_f64_biteq!(nan2.next_down(), nan2); } #[test] -- cgit 1.4.1-3-g733a5 From 85d5171dea32465a3b62acbe7e09fac026a1b20e Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Sat, 19 Feb 2022 12:23:54 +0100 Subject: Float biteq macros can be unused if test is skipped. --- library/std/src/f32/tests.rs | 1 + library/std/src/f64/tests.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs index 0e2f0561ea0..e1f9b3fe19d 100644 --- a/library/std/src/f32/tests.rs +++ b/library/std/src/f32/tests.rs @@ -299,6 +299,7 @@ fn test_is_sign_negative() { assert!((-f32::NAN).is_sign_negative()); } +#[allow(unused_macros)] macro_rules! assert_f32_biteq { ($left : expr, $right : expr) => { let l: &f32 = &$left; diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs index 8125b249227..1619288bedb 100644 --- a/library/std/src/f64/tests.rs +++ b/library/std/src/f64/tests.rs @@ -289,6 +289,7 @@ fn test_is_sign_negative() { assert!((-f64::NAN).is_sign_negative()); } +#[allow(unused_macros)] macro_rules! assert_f64_biteq { ($left : expr, $right : expr) => { let l: &f64 = &$left; -- cgit 1.4.1-3-g733a5 From a1e251024de877f1746e02f856ccb2f666800f5e Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Sat, 19 Feb 2022 19:05:55 +0100 Subject: Semicolon after macro_rules definition. --- library/std/src/f32/tests.rs | 2 +- library/std/src/f64/tests.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs index e1f9b3fe19d..4ec16c84aa9 100644 --- a/library/std/src/f32/tests.rs +++ b/library/std/src/f32/tests.rs @@ -307,7 +307,7 @@ macro_rules! assert_f32_biteq { let lb = l.to_bits(); let rb = r.to_bits(); assert_eq!(lb, rb, "float {} ({:#x}) is not equal to {} ({:#x})", *l, lb, *r, rb); - } + }; } // Ignore test on x87 floating point, these platforms do not guarantee NaN diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs index 1619288bedb..12baa68f49b 100644 --- a/library/std/src/f64/tests.rs +++ b/library/std/src/f64/tests.rs @@ -297,7 +297,7 @@ macro_rules! assert_f64_biteq { let lb = l.to_bits(); let rb = r.to_bits(); assert_eq!(lb, rb, "float {} ({:#x}) is not equal to {} ({:#x})", *l, lb, *r, rb); - } + }; } // Ignore test on x87 floating point, these platforms do not guarantee NaN -- cgit 1.4.1-3-g733a5 From 3f10e6c86d9d602a821b3156266978c33a214965 Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 15 Aug 2022 12:47:05 +0200 Subject: Say that the identity holds only for all finite numbers (aka not NaN) --- library/core/src/num/f32.rs | 4 ++-- library/core/src/num/f64.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index f6cef3f8067..dd956e2aa9a 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -688,7 +688,7 @@ impl f32 { /// - if `self` is [`MAX`] or [`INFINITY`], this returns [`INFINITY`]; /// - otherwise the unique least value greater than `self` is returned. /// - /// The identity `x.next_up() == -(-x).next_down()` holds for all `x`. When `x` + /// The identity `x.next_up() == -(-x).next_down()` holds for all non-NaN `x`. When `x` /// is finite `x == x.next_up().next_down()` also holds. /// /// ```rust @@ -738,7 +738,7 @@ impl f32 { /// - if `self` is [`MIN`] or [`NEG_INFINITY`], this returns [`NEG_INFINITY`]; /// - otherwise the unique greatest value less than `self` is returned. /// - /// The identity `x.next_down() == -(-x).next_up()` holds for all `x`. When `x` + /// The identity `x.next_down() == -(-x).next_up()` holds for all non-NaN `x`. When `x` /// is finite `x == x.next_down().next_up()` also holds. /// /// ```rust diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 328b19b203c..bf11ada4f62 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -698,7 +698,7 @@ impl f64 { /// - if `self` is [`MAX`] or [`INFINITY`], this returns [`INFINITY`]; /// - otherwise the unique least value greater than `self` is returned. /// - /// The identity `x.next_up() == -(-x).next_down()` holds for all `x`. When `x` + /// The identity `x.next_up() == -(-x).next_down()` holds for all non-NaN `x`. When `x` /// is finite `x == x.next_up().next_down()` also holds. /// /// ```rust @@ -748,7 +748,7 @@ impl f64 { /// - if `self` is [`MIN`] or [`NEG_INFINITY`], this returns [`NEG_INFINITY`]; /// - otherwise the unique greatest value less than `self` is returned. /// - /// The identity `x.next_down() == -(-x).next_up()` holds for all `x`. When `x` + /// The identity `x.next_down() == -(-x).next_up()` holds for all non-NaN `x`. When `x` /// is finite `x == x.next_down().next_up()` also holds. /// /// ```rust -- cgit 1.4.1-3-g733a5 From dcbe892d7ceec113a148a89bc6d1c339c55586d1 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 15 Aug 2022 13:51:45 +0200 Subject: Add an HIR pretty-printer --- crates/hir-def/src/body.rs | 5 + crates/hir-def/src/body/pretty.rs | 621 +++++++++++++++++++++++++++++++++ crates/hir-def/src/builtin_type.rs | 35 ++ crates/hir-def/src/expr.rs | 6 +- crates/hir-def/src/item_tree/pretty.rs | 179 +--------- crates/hir-def/src/item_tree/tests.rs | 12 +- crates/hir-def/src/lib.rs | 1 + crates/hir-def/src/pretty.rs | 209 +++++++++++ crates/hir-def/src/type_ref.rs | 4 + crates/hir/src/lib.rs | 29 +- crates/ide/src/view_hir.rs | 14 +- editors/code/src/commands.ts | 2 +- 12 files changed, 914 insertions(+), 203 deletions(-) create mode 100644 crates/hir-def/src/body/pretty.rs create mode 100644 crates/hir-def/src/pretty.rs diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs index 080a307b1f8..1d818d96267 100644 --- a/crates/hir-def/src/body.rs +++ b/crates/hir-def/src/body.rs @@ -4,6 +4,7 @@ mod lower; #[cfg(test)] mod tests; pub mod scope; +mod pretty; use std::{ops::Index, sync::Arc}; @@ -352,6 +353,10 @@ impl Body { } } + pub fn pretty_print(&self, db: &dyn DefDatabase, owner: DefWithBodyId) -> String { + pretty::print_body_hir(db, self, owner) + } + fn new( db: &dyn DefDatabase, expander: Expander, diff --git a/crates/hir-def/src/body/pretty.rs b/crates/hir-def/src/body/pretty.rs new file mode 100644 index 00000000000..ddd476efe5c --- /dev/null +++ b/crates/hir-def/src/body/pretty.rs @@ -0,0 +1,621 @@ +//! A pretty-printer for HIR. + +use std::fmt::{self, Write}; + +use crate::{ + expr::{Array, BindingAnnotation, Literal, Statement}, + pretty::{print_generic_args, print_path, print_type_ref}, + type_ref::TypeRef, +}; + +use super::*; + +pub(super) fn print_body_hir(db: &dyn DefDatabase, body: &Body, owner: DefWithBodyId) -> String { + let needs_semi; + let header = match owner { + DefWithBodyId::FunctionId(it) => { + needs_semi = false; + let item_tree_id = it.lookup(db).id; + format!("fn {}(…) ", item_tree_id.item_tree(db)[item_tree_id.value].name) + } + DefWithBodyId::StaticId(it) => { + needs_semi = true; + let item_tree_id = it.lookup(db).id; + format!("static {} = ", item_tree_id.item_tree(db)[item_tree_id.value].name) + } + DefWithBodyId::ConstId(it) => { + needs_semi = true; + let item_tree_id = it.lookup(db).id; + let name = match &item_tree_id.item_tree(db)[item_tree_id.value].name { + Some(name) => name.to_string(), + None => "_".to_string(), + }; + format!("const {} = ", name) + } + }; + + let mut p = Printer { body, buf: header, indent_level: 0, needs_indent: false }; + p.print_expr(body.body_expr); + if needs_semi { + p.buf.push(';'); + } + p.buf +} + +macro_rules! w { + ($dst:expr, $($arg:tt)*) => { + { let _ = write!($dst, $($arg)*); } + }; +} + +macro_rules! wln { + ($dst:expr) => { + { let _ = writeln!($dst); } + }; + ($dst:expr, $($arg:tt)*) => { + { let _ = writeln!($dst, $($arg)*); } + }; +} + +struct Printer<'a> { + body: &'a Body, + buf: String, + indent_level: usize, + needs_indent: bool, +} + +impl<'a> Write for Printer<'a> { + fn write_str(&mut self, s: &str) -> fmt::Result { + for line in s.split_inclusive('\n') { + if self.needs_indent { + match self.buf.chars().rev().skip_while(|ch| *ch == ' ').next() { + Some('\n') | None => {} + _ => self.buf.push('\n'), + } + self.buf.push_str(&" ".repeat(self.indent_level)); + self.needs_indent = false; + } + + self.buf.push_str(line); + self.needs_indent = line.ends_with('\n'); + } + + Ok(()) + } +} + +impl<'a> Printer<'a> { + fn indented(&mut self, f: impl FnOnce(&mut Self)) { + self.indent_level += 1; + wln!(self); + f(self); + self.indent_level -= 1; + self.buf = self.buf.trim_end_matches('\n').to_string(); + } + + fn whitespace(&mut self) { + match self.buf.chars().next_back() { + None | Some('\n' | ' ') => {} + _ => self.buf.push(' '), + } + } + + fn newline(&mut self) { + match self.buf.chars().rev().skip_while(|ch| *ch == ' ').next() { + Some('\n') | None => {} + _ => writeln!(self).unwrap(), + } + } + + fn print_expr(&mut self, expr: ExprId) { + let expr = &self.body[expr]; + + match expr { + Expr::Missing => w!(self, "�"), + Expr::Underscore => w!(self, "_"), + Expr::Path(path) => self.print_path(path), + Expr::If { condition, then_branch, else_branch } => { + w!(self, "if "); + self.print_expr(*condition); + w!(self, " "); + self.print_expr(*then_branch); + if let Some(els) = *else_branch { + w!(self, " else "); + self.print_expr(els); + } + } + Expr::Let { pat, expr } => { + w!(self, "let "); + self.print_pat(*pat); + w!(self, " = "); + self.print_expr(*expr); + } + Expr::Loop { body, label } => { + if let Some(lbl) = label { + w!(self, "{}: ", self.body[*lbl].name); + } + w!(self, "loop "); + self.print_expr(*body); + } + Expr::While { condition, body, label } => { + if let Some(lbl) = label { + w!(self, "{}: ", self.body[*lbl].name); + } + w!(self, "while "); + self.print_expr(*condition); + self.print_expr(*body); + } + Expr::For { iterable, pat, body, label } => { + if let Some(lbl) = label { + w!(self, "{}: ", self.body[*lbl].name); + } + w!(self, "for "); + self.print_pat(*pat); + w!(self, " in "); + self.print_expr(*iterable); + self.print_expr(*body); + } + Expr::Call { callee, args, is_assignee_expr: _ } => { + self.print_expr(*callee); + w!(self, "("); + if !args.is_empty() { + self.indented(|p| { + for arg in &**args { + p.print_expr(*arg); + wln!(p, ","); + } + }); + } + w!(self, ")"); + } + Expr::MethodCall { receiver, method_name, args, generic_args } => { + self.print_expr(*receiver); + w!(self, ".{}", method_name); + if let Some(args) = generic_args { + w!(self, "::<"); + print_generic_args(args, self).unwrap(); + w!(self, ">"); + } + w!(self, "("); + if !args.is_empty() { + self.indented(|p| { + for arg in &**args { + p.print_expr(*arg); + wln!(p, ","); + } + }); + } + w!(self, ")"); + } + Expr::Match { expr, arms } => { + w!(self, "match "); + self.print_expr(*expr); + w!(self, " {{"); + self.indented(|p| { + for arm in &**arms { + p.print_pat(arm.pat); + if let Some(guard) = arm.guard { + w!(p, " if "); + p.print_expr(guard); + } + w!(p, " => "); + p.print_expr(arm.expr); + wln!(p, ","); + } + }); + wln!(self, "}}"); + } + Expr::Continue { label } => { + w!(self, "continue"); + if let Some(label) = label { + w!(self, " {}", label); + } + } + Expr::Break { expr, label } => { + w!(self, "break"); + if let Some(label) = label { + w!(self, " {}", label); + } + if let Some(expr) = expr { + self.whitespace(); + self.print_expr(*expr); + } + } + Expr::Return { expr } => { + w!(self, "return"); + if let Some(expr) = expr { + self.whitespace(); + self.print_expr(*expr); + } + } + Expr::Yield { expr } => { + w!(self, "yield"); + if let Some(expr) = expr { + self.whitespace(); + self.print_expr(*expr); + } + } + Expr::RecordLit { path, fields, spread, ellipsis, is_assignee_expr: _ } => { + match path { + Some(path) => self.print_path(path), + None => w!(self, "�"), + } + + w!(self, "{{"); + self.indented(|p| { + for field in &**fields { + w!(p, "{}: ", field.name); + p.print_expr(field.expr); + wln!(p, ","); + } + if let Some(spread) = spread { + w!(p, ".."); + p.print_expr(*spread); + wln!(p); + } + if *ellipsis { + wln!(p, ".."); + } + }); + w!(self, "}}"); + } + Expr::Field { expr, name } => { + self.print_expr(*expr); + w!(self, ".{}", name); + } + Expr::Await { expr } => { + self.print_expr(*expr); + w!(self, ".await"); + } + Expr::Try { expr } => { + self.print_expr(*expr); + w!(self, "?"); + } + Expr::TryBlock { body } => { + w!(self, "try "); + self.print_expr(*body); + } + Expr::Async { body } => { + w!(self, "async "); + self.print_expr(*body); + } + Expr::Const { body } => { + w!(self, "const "); + self.print_expr(*body); + } + Expr::Cast { expr, type_ref } => { + self.print_expr(*expr); + w!(self, " as "); + self.print_type_ref(type_ref); + } + Expr::Ref { expr, rawness, mutability } => { + w!(self, "&"); + if rawness.is_raw() { + w!(self, "raw "); + } + if mutability.is_mut() { + w!(self, "mut "); + } + self.print_expr(*expr); + } + Expr::Box { expr } => { + w!(self, "box "); + self.print_expr(*expr); + } + Expr::UnaryOp { expr, op } => { + let op = match op { + ast::UnaryOp::Deref => "*", + ast::UnaryOp::Not => "!", + ast::UnaryOp::Neg => "-", + }; + w!(self, "{}", op); + self.print_expr(*expr); + } + Expr::BinaryOp { lhs, rhs, op } => { + let (bra, ket) = match op { + None | Some(ast::BinaryOp::Assignment { .. }) => ("", ""), + _ => ("(", ")"), + }; + w!(self, "{}", bra); + self.print_expr(*lhs); + w!(self, "{} ", ket); + match op { + Some(op) => w!(self, "{}", op), + None => w!(self, "�"), // :) + } + w!(self, " {}", bra); + self.print_expr(*rhs); + w!(self, "{}", ket); + } + Expr::Range { lhs, rhs, range_type } => { + if let Some(lhs) = lhs { + w!(self, "("); + self.print_expr(*lhs); + w!(self, ") "); + } + let range = match range_type { + ast::RangeOp::Exclusive => "..", + ast::RangeOp::Inclusive => "..=", + }; + w!(self, "{}", range); + if let Some(rhs) = rhs { + w!(self, "("); + self.print_expr(*rhs); + w!(self, ") "); + } + } + Expr::Index { base, index } => { + self.print_expr(*base); + w!(self, "["); + self.print_expr(*index); + w!(self, "]"); + } + Expr::Closure { args, arg_types, ret_type, body } => { + w!(self, "|"); + for (i, (pat, ty)) in args.iter().zip(arg_types.iter()).enumerate() { + if i != 0 { + w!(self, ", "); + } + self.print_pat(*pat); + if let Some(ty) = ty { + w!(self, ": "); + self.print_type_ref(ty); + } + } + w!(self, "|"); + if let Some(ret_ty) = ret_type { + w!(self, " -> "); + self.print_type_ref(ret_ty); + } + self.whitespace(); + self.print_expr(*body); + } + Expr::Tuple { exprs, is_assignee_expr: _ } => { + w!(self, "("); + for expr in exprs.iter() { + self.print_expr(*expr); + w!(self, ", "); + } + w!(self, ")"); + } + Expr::Unsafe { body } => { + w!(self, "unsafe "); + self.print_expr(*body); + } + Expr::Array(arr) => { + w!(self, "["); + if !matches!(arr, Array::ElementList { elements, .. } if elements.is_empty()) { + self.indented(|p| match arr { + Array::ElementList { elements, is_assignee_expr: _ } => { + for elem in elements.iter() { + p.print_expr(*elem); + w!(p, ", "); + } + } + Array::Repeat { initializer, repeat } => { + p.print_expr(*initializer); + w!(p, "; "); + p.print_expr(*repeat); + } + }); + self.newline(); + } + w!(self, "]"); + } + Expr::Literal(lit) => self.print_literal(lit), + Expr::Block { id: _, statements, tail, label } => { + self.whitespace(); + if let Some(lbl) = label { + w!(self, "{}: ", self.body[*lbl].name); + } + w!(self, "{{"); + if !statements.is_empty() || tail.is_some() { + self.indented(|p| { + for stmt in &**statements { + p.print_stmt(stmt); + } + if let Some(tail) = tail { + p.print_expr(*tail); + } + p.newline(); + }); + } + w!(self, "}}"); + } + Expr::MacroStmts { statements, tail } => { + w!(self, "{{ // macro statements"); + self.indented(|p| { + for stmt in statements.iter() { + p.print_stmt(stmt); + } + if let Some(tail) = tail { + p.print_expr(*tail); + } + }); + self.newline(); + w!(self, "}}"); + } + } + } + + fn print_pat(&mut self, pat: PatId) { + let pat = &self.body[pat]; + + match pat { + Pat::Missing => w!(self, "�"), + Pat::Wild => w!(self, "_"), + Pat::Tuple { args, ellipsis } => { + w!(self, "("); + for (i, pat) in args.iter().enumerate() { + if i != 0 { + w!(self, ", "); + } + if *ellipsis == Some(i) { + w!(self, ".., "); + } + self.print_pat(*pat); + } + w!(self, ")"); + } + Pat::Or(pats) => { + for (i, pat) in pats.iter().enumerate() { + if i != 0 { + w!(self, " | "); + } + self.print_pat(*pat); + } + } + Pat::Record { path, args, ellipsis } => { + match path { + Some(path) => self.print_path(path), + None => w!(self, "�"), + } + + w!(self, " {{"); + self.indented(|p| { + for arg in args.iter() { + w!(p, "{}: ", arg.name); + p.print_pat(arg.pat); + wln!(p, ","); + } + if *ellipsis { + wln!(p, ".."); + } + }); + w!(self, "}}"); + } + Pat::Range { start, end } => { + self.print_expr(*start); + w!(self, "..."); + self.print_expr(*end); + } + Pat::Slice { prefix, slice, suffix } => { + w!(self, "["); + for pat in prefix.iter() { + self.print_pat(*pat); + w!(self, ", "); + } + if let Some(pat) = slice { + self.print_pat(*pat); + w!(self, ", "); + } + for pat in suffix.iter() { + self.print_pat(*pat); + w!(self, ", "); + } + w!(self, "]"); + } + Pat::Path(path) => self.print_path(path), + Pat::Lit(expr) => self.print_expr(*expr), + Pat::Bind { mode, name, subpat } => { + let mode = match mode { + BindingAnnotation::Unannotated => "", + BindingAnnotation::Mutable => "mut ", + BindingAnnotation::Ref => "ref ", + BindingAnnotation::RefMut => "ref mut ", + }; + w!(self, "{}{}", mode, name); + if let Some(pat) = subpat { + self.whitespace(); + self.print_pat(*pat); + } + } + Pat::TupleStruct { path, args, ellipsis } => { + match path { + Some(path) => self.print_path(path), + None => w!(self, "�"), + } + w!(self, "("); + for (i, arg) in args.iter().enumerate() { + if i != 0 { + w!(self, ", "); + } + if *ellipsis == Some(i) { + w!(self, ", .."); + } + self.print_pat(*arg); + } + w!(self, ")"); + } + Pat::Ref { pat, mutability } => { + w!(self, "&"); + if mutability.is_mut() { + w!(self, "mut "); + } + self.print_pat(*pat); + } + Pat::Box { inner } => { + w!(self, "box "); + self.print_pat(*inner); + } + Pat::ConstBlock(c) => { + w!(self, "const "); + self.print_expr(*c); + } + } + } + + fn print_stmt(&mut self, stmt: &Statement) { + match stmt { + Statement::Let { pat, type_ref, initializer, else_branch } => { + w!(self, "let "); + self.print_pat(*pat); + if let Some(ty) = type_ref { + w!(self, ": "); + self.print_type_ref(ty); + } + if let Some(init) = initializer { + w!(self, " = "); + self.print_expr(*init); + } + if let Some(els) = else_branch { + w!(self, " else "); + self.print_expr(*els); + } + wln!(self, ";"); + } + Statement::Expr { expr, has_semi } => { + self.print_expr(*expr); + if *has_semi { + w!(self, ";"); + } + wln!(self); + } + } + } + + fn print_literal(&mut self, literal: &Literal) { + match literal { + Literal::String(it) => w!(self, "{:?}", it), + Literal::ByteString(it) => w!(self, "\"{}\"", it.escape_ascii()), + Literal::Char(it) => w!(self, "'{}'", it.escape_debug()), + Literal::Bool(it) => w!(self, "{}", it), + Literal::Int(i, suffix) => { + w!(self, "{}", i); + if let Some(suffix) = suffix { + w!(self, "{}", suffix); + } + } + Literal::Uint(i, suffix) => { + w!(self, "{}", i); + if let Some(suffix) = suffix { + w!(self, "{}", suffix); + } + } + Literal::Float(f, suffix) => { + w!(self, "{}", f); + if let Some(suffix) = suffix { + w!(self, "{}", suffix); + } + } + } + } + + fn print_type_ref(&mut self, ty: &TypeRef) { + print_type_ref(ty, self).unwrap(); + } + + fn print_path(&mut self, path: &Path) { + print_path(path, self).unwrap(); + } +} diff --git a/crates/hir-def/src/builtin_type.rs b/crates/hir-def/src/builtin_type.rs index 25a408036ff..dd69c3ab473 100644 --- a/crates/hir-def/src/builtin_type.rs +++ b/crates/hir-def/src/builtin_type.rs @@ -156,3 +156,38 @@ impl BuiltinFloat { Some(res) } } + +impl fmt::Display for BuiltinInt { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + BuiltinInt::Isize => "isize", + BuiltinInt::I8 => "i8", + BuiltinInt::I16 => "i16", + BuiltinInt::I32 => "i32", + BuiltinInt::I64 => "i64", + BuiltinInt::I128 => "i128", + }) + } +} + +impl fmt::Display for BuiltinUint { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + BuiltinUint::Usize => "usize", + BuiltinUint::U8 => "u8", + BuiltinUint::U16 => "u16", + BuiltinUint::U32 => "u32", + BuiltinUint::U64 => "u64", + BuiltinUint::U128 => "u128", + }) + } +} + +impl fmt::Display for BuiltinFloat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + BuiltinFloat::F32 => "f32", + BuiltinFloat::F64 => "f64", + }) + } +} diff --git a/crates/hir-def/src/expr.rs b/crates/hir-def/src/expr.rs index c1b3788acb7..4381b43c258 100644 --- a/crates/hir-def/src/expr.rs +++ b/crates/hir-def/src/expr.rs @@ -12,6 +12,8 @@ //! //! See also a neighboring `body` module. +use std::fmt; + use hir_expand::name::Name; use la_arena::{Idx, RawIdx}; @@ -52,8 +54,8 @@ impl FloatTypeWrapper { } } -impl std::fmt::Display for FloatTypeWrapper { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl fmt::Display for FloatTypeWrapper { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", f64::from_bits(self.0)) } } diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs index f12d9a1273c..34dd817fd13 100644 --- a/crates/hir-def/src/item_tree/pretty.rs +++ b/crates/hir-def/src/item_tree/pretty.rs @@ -2,13 +2,10 @@ use std::fmt::{self, Write}; -use itertools::Itertools; - use crate::{ attr::RawAttrs, generics::{TypeOrConstParamData, WherePredicate, WherePredicateTypeTarget}, - path::GenericArg, - type_ref::TraitBoundModifier, + pretty::{print_path, print_type_bounds, print_type_ref}, visibility::RawVisibility, }; @@ -464,183 +461,15 @@ impl<'a> Printer<'a> { } fn print_type_ref(&mut self, type_ref: &TypeRef) { - // FIXME: deduplicate with `HirDisplay` impl - match type_ref { - TypeRef::Never => w!(self, "!"), - TypeRef::Placeholder => w!(self, "_"), - TypeRef::Tuple(fields) => { - w!(self, "("); - for (i, field) in fields.iter().enumerate() { - if i != 0 { - w!(self, ", "); - } - self.print_type_ref(field); - } - w!(self, ")"); - } - TypeRef::Path(path) => self.print_path(path), - TypeRef::RawPtr(pointee, mtbl) => { - let mtbl = match mtbl { - Mutability::Shared => "*const", - Mutability::Mut => "*mut", - }; - w!(self, "{} ", mtbl); - self.print_type_ref(pointee); - } - TypeRef::Reference(pointee, lt, mtbl) => { - let mtbl = match mtbl { - Mutability::Shared => "", - Mutability::Mut => "mut ", - }; - w!(self, "&"); - if let Some(lt) = lt { - w!(self, "{} ", lt.name); - } - w!(self, "{}", mtbl); - self.print_type_ref(pointee); - } - TypeRef::Array(elem, len) => { - w!(self, "["); - self.print_type_ref(elem); - w!(self, "; {}]", len); - } - TypeRef::Slice(elem) => { - w!(self, "["); - self.print_type_ref(elem); - w!(self, "]"); - } - TypeRef::Fn(args_and_ret, varargs) => { - let ((_, return_type), args) = - args_and_ret.split_last().expect("TypeRef::Fn is missing return type"); - w!(self, "fn("); - for (i, (_, typeref)) in args.iter().enumerate() { - if i != 0 { - w!(self, ", "); - } - self.print_type_ref(typeref); - } - if *varargs { - if !args.is_empty() { - w!(self, ", "); - } - w!(self, "..."); - } - w!(self, ") -> "); - self.print_type_ref(return_type); - } - TypeRef::Macro(_ast_id) => { - w!(self, ""); - } - TypeRef::Error => w!(self, "{{unknown}}"), - TypeRef::ImplTrait(bounds) => { - w!(self, "impl "); - self.print_type_bounds(bounds); - } - TypeRef::DynTrait(bounds) => { - w!(self, "dyn "); - self.print_type_bounds(bounds); - } - } + print_type_ref(type_ref, self).unwrap(); } fn print_type_bounds(&mut self, bounds: &[Interned]) { - for (i, bound) in bounds.iter().enumerate() { - if i != 0 { - w!(self, " + "); - } - - match bound.as_ref() { - TypeBound::Path(path, modifier) => { - match modifier { - TraitBoundModifier::None => (), - TraitBoundModifier::Maybe => w!(self, "?"), - } - self.print_path(path) - } - TypeBound::ForLifetime(lifetimes, path) => { - w!(self, "for<{}> ", lifetimes.iter().format(", ")); - self.print_path(path); - } - TypeBound::Lifetime(lt) => w!(self, "{}", lt.name), - TypeBound::Error => w!(self, "{{unknown}}"), - } - } + print_type_bounds(bounds, self).unwrap(); } fn print_path(&mut self, path: &Path) { - match path.type_anchor() { - Some(anchor) => { - w!(self, "<"); - self.print_type_ref(anchor); - w!(self, ">::"); - } - None => match path.kind() { - PathKind::Plain => {} - PathKind::Super(0) => w!(self, "self::"), - PathKind::Super(n) => { - for _ in 0..*n { - w!(self, "super::"); - } - } - PathKind::Crate => w!(self, "crate::"), - PathKind::Abs => w!(self, "::"), - PathKind::DollarCrate(_) => w!(self, "$crate::"), - }, - } - - for (i, segment) in path.segments().iter().enumerate() { - if i != 0 { - w!(self, "::"); - } - - w!(self, "{}", segment.name); - if let Some(generics) = segment.args_and_bindings { - // NB: these are all in type position, so `::<` turbofish syntax is not necessary - w!(self, "<"); - let mut first = true; - let args = if generics.has_self_type { - let (self_ty, args) = generics.args.split_first().unwrap(); - w!(self, "Self="); - self.print_generic_arg(self_ty); - first = false; - args - } else { - &generics.args - }; - for arg in args { - if !first { - w!(self, ", "); - } - first = false; - self.print_generic_arg(arg); - } - for binding in &generics.bindings { - if !first { - w!(self, ", "); - } - first = false; - w!(self, "{}", binding.name); - if !binding.bounds.is_empty() { - w!(self, ": "); - self.print_type_bounds(&binding.bounds); - } - if let Some(ty) = &binding.type_ref { - w!(self, " = "); - self.print_type_ref(ty); - } - } - - w!(self, ">"); - } - } - } - - fn print_generic_arg(&mut self, arg: &GenericArg) { - match arg { - GenericArg::Type(ty) => self.print_type_ref(ty), - GenericArg::Const(c) => w!(self, "{}", c), - GenericArg::Lifetime(lt) => w!(self, "{}", lt.name), - } + print_path(path, self).unwrap(); } fn print_generic_params(&mut self, params: &GenericParams) { diff --git a/crates/hir-def/src/item_tree/tests.rs b/crates/hir-def/src/item_tree/tests.rs index 5cdf36cc61b..e30d9652bb5 100644 --- a/crates/hir-def/src/item_tree/tests.rs +++ b/crates/hir-def/src/item_tree/tests.rs @@ -283,10 +283,10 @@ struct S { "#, expect![[r#" pub(self) struct S { - pub(self) a: Mixed<'a, T, Item = (), OtherItem = u8>, - pub(self) b: Qualified::Syntax, - pub(self) c: ::Path<'a>, - pub(self) d: dyn for<'a> Trait<'a>, + pub(self) a: Mixed::<'a, T, Item = (), OtherItem = u8>, + pub(self) b: Qualified::::Syntax, + pub(self) c: ::Path::<'a>, + pub(self) d: dyn for<'a> Trait::<'a>, } "#]], ) @@ -329,7 +329,7 @@ trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {} T: Copy, U: ?Sized; - impl<'a, 'b, T, const K: u8> S<'a, 'b, T, K> + impl<'a, 'b, T, const K: u8> S::<'a, 'b, T, K> where T: Copy, T: 'a, @@ -352,7 +352,7 @@ trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {} where Self: Super, T: 'a, - Self: for<'a> Tr<'a, T> + Self: for<'a> Tr::<'a, T> { } "#]], diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 56603f4b154..32ebfda4fd9 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -53,6 +53,7 @@ pub mod import_map; mod test_db; #[cfg(test)] mod macro_expansion_tests; +mod pretty; use std::{ hash::{Hash, Hasher}, diff --git a/crates/hir-def/src/pretty.rs b/crates/hir-def/src/pretty.rs new file mode 100644 index 00000000000..6636c8a23ca --- /dev/null +++ b/crates/hir-def/src/pretty.rs @@ -0,0 +1,209 @@ +//! Display and pretty printing routines. + +use std::fmt::{self, Write}; + +use hir_expand::mod_path::PathKind; +use itertools::Itertools; + +use crate::{ + intern::Interned, + path::{GenericArg, GenericArgs, Path}, + type_ref::{Mutability, TraitBoundModifier, TypeBound, TypeRef}, +}; + +pub(crate) fn print_path(path: &Path, buf: &mut dyn Write) -> fmt::Result { + match path.type_anchor() { + Some(anchor) => { + write!(buf, "<")?; + print_type_ref(anchor, buf)?; + write!(buf, ">::")?; + } + None => match path.kind() { + PathKind::Plain => {} + PathKind::Super(0) => write!(buf, "self")?, + PathKind::Super(n) => { + for i in 0..*n { + if i == 0 { + buf.write_str("super")?; + } else { + buf.write_str("::super")?; + } + } + } + PathKind::Crate => write!(buf, "crate")?, + PathKind::Abs => {} + PathKind::DollarCrate(_) => write!(buf, "$crate")?, + }, + } + + for (i, segment) in path.segments().iter().enumerate() { + if i != 0 || !matches!(path.kind(), PathKind::Plain) { + write!(buf, "::")?; + } + + write!(buf, "{}", segment.name)?; + if let Some(generics) = segment.args_and_bindings { + write!(buf, "::<")?; + print_generic_args(generics, buf)?; + + write!(buf, ">")?; + } + } + + Ok(()) +} + +pub(crate) fn print_generic_args(generics: &GenericArgs, buf: &mut dyn Write) -> fmt::Result { + let mut first = true; + let args = if generics.has_self_type { + let (self_ty, args) = generics.args.split_first().unwrap(); + write!(buf, "Self=")?; + print_generic_arg(self_ty, buf)?; + first = false; + args + } else { + &generics.args + }; + for arg in args { + if !first { + write!(buf, ", ")?; + } + first = false; + print_generic_arg(arg, buf)?; + } + for binding in &generics.bindings { + if !first { + write!(buf, ", ")?; + } + first = false; + write!(buf, "{}", binding.name)?; + if !binding.bounds.is_empty() { + write!(buf, ": ")?; + print_type_bounds(&binding.bounds, buf)?; + } + if let Some(ty) = &binding.type_ref { + write!(buf, " = ")?; + print_type_ref(ty, buf)?; + } + } + Ok(()) +} + +pub(crate) fn print_generic_arg(arg: &GenericArg, buf: &mut dyn Write) -> fmt::Result { + match arg { + GenericArg::Type(ty) => print_type_ref(ty, buf), + GenericArg::Const(c) => write!(buf, "{}", c), + GenericArg::Lifetime(lt) => write!(buf, "{}", lt.name), + } +} + +pub(crate) fn print_type_ref(type_ref: &TypeRef, buf: &mut dyn Write) -> fmt::Result { + // FIXME: deduplicate with `HirDisplay` impl + match type_ref { + TypeRef::Never => write!(buf, "!")?, + TypeRef::Placeholder => write!(buf, "_")?, + TypeRef::Tuple(fields) => { + write!(buf, "(")?; + for (i, field) in fields.iter().enumerate() { + if i != 0 { + write!(buf, ", ")?; + } + print_type_ref(field, buf)?; + } + write!(buf, ")")?; + } + TypeRef::Path(path) => print_path(path, buf)?, + TypeRef::RawPtr(pointee, mtbl) => { + let mtbl = match mtbl { + Mutability::Shared => "*const", + Mutability::Mut => "*mut", + }; + write!(buf, "{} ", mtbl)?; + print_type_ref(pointee, buf)?; + } + TypeRef::Reference(pointee, lt, mtbl) => { + let mtbl = match mtbl { + Mutability::Shared => "", + Mutability::Mut => "mut ", + }; + write!(buf, "&")?; + if let Some(lt) = lt { + write!(buf, "{} ", lt.name)?; + } + write!(buf, "{}", mtbl)?; + print_type_ref(pointee, buf)?; + } + TypeRef::Array(elem, len) => { + write!(buf, "[")?; + print_type_ref(elem, buf)?; + write!(buf, "; {}]", len)?; + } + TypeRef::Slice(elem) => { + write!(buf, "[")?; + print_type_ref(elem, buf)?; + write!(buf, "]")?; + } + TypeRef::Fn(args_and_ret, varargs) => { + let ((_, return_type), args) = + args_and_ret.split_last().expect("TypeRef::Fn is missing return type"); + write!(buf, "fn(")?; + for (i, (_, typeref)) in args.iter().enumerate() { + if i != 0 { + write!(buf, ", ")?; + } + print_type_ref(typeref, buf)?; + } + if *varargs { + if !args.is_empty() { + write!(buf, ", ")?; + } + write!(buf, "...")?; + } + write!(buf, ") -> ")?; + print_type_ref(return_type, buf)?; + } + TypeRef::Macro(_ast_id) => { + write!(buf, "")?; + } + TypeRef::Error => write!(buf, "{{unknown}}")?, + TypeRef::ImplTrait(bounds) => { + write!(buf, "impl ")?; + print_type_bounds(bounds, buf)?; + } + TypeRef::DynTrait(bounds) => { + write!(buf, "dyn ")?; + print_type_bounds(bounds, buf)?; + } + } + + Ok(()) +} + +pub(crate) fn print_type_bounds( + bounds: &[Interned], + buf: &mut dyn Write, +) -> fmt::Result { + for (i, bound) in bounds.iter().enumerate() { + if i != 0 { + write!(buf, " + ")?; + } + + match bound.as_ref() { + TypeBound::Path(path, modifier) => { + match modifier { + TraitBoundModifier::None => (), + TraitBoundModifier::Maybe => write!(buf, "?")?, + } + print_path(path, buf)?; + } + TypeBound::ForLifetime(lifetimes, path) => { + write!(buf, "for<{}> ", lifetimes.iter().format(", "))?; + print_path(path, buf)?; + } + TypeBound::Lifetime(lt) => write!(buf, "{}", lt.name)?, + TypeBound::Error => write!(buf, "{{unknown}}")?, + } + } + + Ok(()) +} diff --git a/crates/hir-def/src/type_ref.rs b/crates/hir-def/src/type_ref.rs index 9248059627d..5b4c71be7fb 100644 --- a/crates/hir-def/src/type_ref.rs +++ b/crates/hir-def/src/type_ref.rs @@ -77,6 +77,10 @@ impl Rawness { Rawness::Ref } } + + pub fn is_raw(&self) -> bool { + matches!(self, Self::RawPtr) + } } #[derive(Clone, PartialEq, Eq, Hash, Debug)] diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 8f984210e11..3561bdeba7f 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -72,7 +72,7 @@ use itertools::Itertools; use nameres::diagnostics::DefDiagnosticKind; use once_cell::unsync::Lazy; use rustc_hash::FxHashSet; -use stdx::{format_to, impl_from, never}; +use stdx::{impl_from, never}; use syntax::{ ast::{self, HasAttrs as _, HasDocComments, HasName}, AstNode, AstPtr, SmolStr, SyntaxNodePtr, TextRange, T, @@ -1136,6 +1136,20 @@ impl DefWithBody { } } + fn id(&self) -> DefWithBodyId { + match self { + DefWithBody::Function(it) => it.id.into(), + DefWithBody::Static(it) => it.id.into(), + DefWithBody::Const(it) => it.id.into(), + } + } + + /// A textual representation of the HIR of this def's body for debugging purposes. + pub fn debug_hir(self, db: &dyn HirDatabase) -> String { + let body = db.body(self.id()); + body.pretty_print(db.upcast(), self.id()) + } + pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec) { let krate = self.module(db).id.krate(); @@ -1470,19 +1484,6 @@ impl Function { let def_map = db.crate_def_map(loc.krate(db).into()); def_map.fn_as_proc_macro(self.id).map(|id| Macro { id: id.into() }) } - - /// A textual representation of the HIR of this function for debugging purposes. - pub fn debug_hir(self, db: &dyn HirDatabase) -> String { - let body = db.body(self.id.into()); - - let mut result = String::new(); - format_to!(result, "HIR expressions in the body of `{}`:\n", self.name(db)); - for (id, expr) in body.exprs.iter() { - format_to!(result, "{:?}: {:?}\n", id, expr); - } - - result - } } // Note: logically, this belongs to `hir_ty`, but we are not using it there yet. diff --git a/crates/ide/src/view_hir.rs b/crates/ide/src/view_hir.rs index bf0835ed7e0..d2bbbf6d26a 100644 --- a/crates/ide/src/view_hir.rs +++ b/crates/ide/src/view_hir.rs @@ -1,4 +1,4 @@ -use hir::{Function, Semantics}; +use hir::{DefWithBody, Semantics}; use ide_db::base_db::FilePosition; use ide_db::RootDatabase; use syntax::{algo::find_node_at_offset, ast, AstNode}; @@ -19,8 +19,12 @@ fn body_hir(db: &RootDatabase, position: FilePosition) -> Option { let sema = Semantics::new(db); let source_file = sema.parse(position.file_id); - let function = find_node_at_offset::(source_file.syntax(), position.offset)?; - - let function: Function = sema.to_def(&function)?; - Some(function.debug_hir(db)) + let item = find_node_at_offset::(source_file.syntax(), position.offset)?; + let def: DefWithBody = match item { + ast::Item::Fn(it) => sema.to_def(&it)?.into(), + ast::Item::Const(it) => sema.to_def(&it)?.into(), + ast::Item::Static(it) => sema.to_def(&it)?.into(), + _ => return None, + }; + Some(def.debug_hir(db)) } diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts index 1b793bb0b15..f58de9da1bf 100644 --- a/editors/code/src/commands.ts +++ b/editors/code/src/commands.ts @@ -433,7 +433,7 @@ export function syntaxTree(ctx: Ctx): Cmd { // The contents of the file come from the `TextDocumentContentProvider` export function viewHir(ctx: Ctx): Cmd { const tdcp = new (class implements vscode.TextDocumentContentProvider { - readonly uri = vscode.Uri.parse("rust-analyzer-hir://viewHir/hir.txt"); + readonly uri = vscode.Uri.parse("rust-analyzer-hir://viewHir/hir.rs"); readonly eventEmitter = new vscode.EventEmitter(); constructor() { vscode.workspace.onDidChangeTextDocument( -- cgit 1.4.1-3-g733a5 From 8e80c39d2ddfaf2fcba084db2e32b2db461d94c7 Mon Sep 17 00:00:00 2001 From: Titus Date: Mon, 15 Aug 2022 16:18:00 +0200 Subject: Fix trailing space showing up in example The current text is rendered as: U+005B ..= U+0060 ``[ \ ] ^ _ ` ``, or. This patch changes that to render as: U+005B ..= U+0060 `` [ \ ] ^ _ ` ``, or The reason for that, is that CommonMark has a solution for starting or ending inline code with a backtick/grave accent: padding both sides with a space, makes that padding disappear. --- library/core/src/num/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index f481399fdcf..72b6dc28185 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -623,7 +623,7 @@ impl u8 { /// /// - U+0021 ..= U+002F `! " # $ % & ' ( ) * + , - . /`, or /// - U+003A ..= U+0040 `: ; < = > ? @`, or - /// - U+005B ..= U+0060 ``[ \ ] ^ _ ` ``, or + /// - U+005B ..= U+0060 `` [ \ ] ^ _ ` ``, or /// - U+007B ..= U+007E `{ | } ~` /// /// # Examples -- cgit 1.4.1-3-g733a5 From 1cac888e4361aea0abbaf8c0ee52509f1742bfe0 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 15 Aug 2022 16:21:41 +0200 Subject: Rustup to rustc 1.65.0-nightly (801821d15 2022-08-14) --- build_sysroot/Cargo.lock | 8 ++++---- rust-toolchain | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build_sysroot/Cargo.lock b/build_sysroot/Cargo.lock index e9bd9167acd..9713f13ccb3 100644 --- a/build_sysroot/Cargo.lock +++ b/build_sysroot/Cargo.lock @@ -56,9 +56,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.78" +version = "0.1.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413b6b13f725a46cdec40364e0c1d564a22cf0aaac5f1e267a129d956478a6b4" +checksum = "4f873ce2bd3550b0b565f878b3d04ea8253f4259dc3d20223af2e1ba86f5ecca" dependencies = [ "rustc-std-workspace-core", ] @@ -135,9 +135,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.127" +version = "0.2.131" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b" +checksum = "04c3b4822ccebfa39c02fc03d1534441b22ead323fa0f48bb7ddd8e6ba076a40" dependencies = [ "rustc-std-workspace-core", ] diff --git a/rust-toolchain b/rust-toolchain index 9b9ed85f6c7..1405265959d 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2022-08-08" +channel = "nightly-2022-08-15" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] -- cgit 1.4.1-3-g733a5 From 3f149a63d226cbdedd466d872677da765ada9df8 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 15 Aug 2022 16:16:59 +0200 Subject: Simplify --- crates/hir-expand/src/ast_id_map.rs | 21 ++++++++------------- crates/hir-expand/src/db.rs | 6 +++++- crates/hir-expand/src/lib.rs | 1 - crates/ide/src/hover.rs | 2 ++ 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/crates/hir-expand/src/ast_id_map.rs b/crates/hir-expand/src/ast_id_map.rs index c1ddef03ba3..11c0a6764e9 100644 --- a/crates/hir-expand/src/ast_id_map.rs +++ b/crates/hir-expand/src/ast_id_map.rs @@ -15,7 +15,7 @@ use std::{ use la_arena::{Arena, Idx}; use profile::Count; use rustc_hash::FxHasher; -use syntax::{ast, match_ast, AstNode, AstPtr, SyntaxNode, SyntaxNodePtr}; +use syntax::{ast, AstNode, AstPtr, SyntaxNode, SyntaxNodePtr}; /// `AstId` points to an AST node in a specific file. pub struct FileAstId { @@ -92,18 +92,12 @@ impl AstIdMap { // change parent's id. This means that, say, adding a new function to a // trait does not change ids of top-level items, which helps caching. bdfs(node, |it| { - match_ast! { - match it { - ast::Item(module_item) => { - res.alloc(module_item.syntax()); - true - }, - ast::BlockExpr(block) => { - res.alloc(block.syntax()); - true - }, - _ => false, - } + let kind = it.kind(); + if ast::Item::can_cast(kind) || ast::BlockExpr::can_cast(kind) { + res.alloc(&it); + true + } else { + false } }); res.map = hashbrown::HashMap::with_capacity_and_hasher(res.arena.len(), ()); @@ -123,6 +117,7 @@ impl AstIdMap { let raw = self.erased_ast_id(item.syntax()); FileAstId { raw, _ty: PhantomData } } + fn erased_ast_id(&self, item: &SyntaxNode) -> ErasedFileAstId { let ptr = SyntaxNodePtr::new(item); let hash = hash_ptr(&ptr); diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs index bd60c3d2686..bc97ee15c7d 100644 --- a/crates/hir-expand/src/db.rs +++ b/crates/hir-expand/src/db.rs @@ -321,7 +321,11 @@ fn censor_for_macro_input(loc: &MacroCallLoc, node: &SyntaxNode) -> FxHashSet), BuiltIn(BuiltinFnLikeExpander, AstId), - // FIXME: maybe just Builtin and rename BuiltinFnLikeExpander to BuiltinExpander BuiltInAttr(BuiltinAttrExpander, AstId), BuiltInDerive(BuiltinDeriveExpander, AstId), BuiltInEager(EagerExpander, AstId), diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 3ada181f1ed..fa2c6f09ab4 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -119,6 +119,8 @@ pub(crate) fn hover( } let in_attr = matches!(original_token.parent().and_then(ast::TokenTree::cast), Some(tt) if tt.syntax().ancestors().any(|it| ast::Meta::can_cast(it.kind()))); + // prefer descending the same token kind in attribute expansions, in normal macros text + // equivalency is more important let descended = if in_attr { [sema.descend_into_macros_with_kind_preference(original_token.clone())].into() } else { -- cgit 1.4.1-3-g733a5 From 88b19cc39b14446cc12e02a20c6f489f9883b760 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 15 Aug 2022 16:41:51 +0200 Subject: Make resolve_name_in_module a bit more lazy --- crates/hir-def/src/nameres/path_resolution.rs | 32 +++++++++++++-------------- crates/hir-def/src/per_ns.rs | 12 ++++++++++ 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs index cc5fc0a52a1..32514ffb135 100644 --- a/crates/hir-def/src/nameres/path_resolution.rs +++ b/crates/hir-def/src/nameres/path_resolution.rs @@ -397,14 +397,15 @@ impl DefMap { Some(_) | None => from_scope.or(from_builtin), }, }; - let from_extern_prelude = self - .extern_prelude - .get(name) - .map_or(PerNs::none(), |&it| PerNs::types(it.into(), Visibility::Public)); - let from_prelude = self.resolve_in_prelude(db, name); + let extern_prelude = || { + self.extern_prelude + .get(name) + .map_or(PerNs::none(), |&it| PerNs::types(it.into(), Visibility::Public)) + }; + let prelude = || self.resolve_in_prelude(db, name); - from_legacy_macro.or(from_scope_or_builtin).or(from_extern_prelude).or(from_prelude) + from_legacy_macro.or(from_scope_or_builtin).or_else(extern_prelude).or_else(prelude) } fn resolve_name_in_crate_root_or_extern_prelude( @@ -412,20 +413,19 @@ impl DefMap { db: &dyn DefDatabase, name: &Name, ) -> PerNs { - let arc; - let crate_def_map = match self.block { + let from_crate_root = match self.block { Some(_) => { - arc = self.crate_root(db).def_map(db); - &arc + let def_map = self.crate_root(db).def_map(db); + def_map[def_map.root].scope.get(name) } - None => self, + None => self[self.root].scope.get(name), + }; + let from_extern_prelude = || { + self.resolve_name_in_extern_prelude(db, name) + .map_or(PerNs::none(), |it| PerNs::types(it.into(), Visibility::Public)) }; - let from_crate_root = crate_def_map[crate_def_map.root].scope.get(name); - let from_extern_prelude = self - .resolve_name_in_extern_prelude(db, name) - .map_or(PerNs::none(), |it| PerNs::types(it.into(), Visibility::Public)); - from_crate_root.or(from_extern_prelude) + from_crate_root.or_else(from_extern_prelude) } fn resolve_in_prelude(&self, db: &dyn DefDatabase, name: &Name) -> PerNs { diff --git a/crates/hir-def/src/per_ns.rs b/crates/hir-def/src/per_ns.rs index bf5bf10c4ca..2bc1f8e926e 100644 --- a/crates/hir-def/src/per_ns.rs +++ b/crates/hir-def/src/per_ns.rs @@ -43,6 +43,10 @@ impl PerNs { self.types.is_none() && self.values.is_none() && self.macros.is_none() } + pub fn is_full(&self) -> bool { + self.types.is_some() && self.values.is_some() && self.macros.is_some() + } + pub fn take_types(self) -> Option { self.types.map(|it| it.0) } @@ -84,6 +88,14 @@ impl PerNs { } } + pub fn or_else(self, f: impl FnOnce() -> PerNs) -> PerNs { + if self.is_full() { + self + } else { + self.or(f()) + } + } + pub fn iter_items(self) -> impl Iterator { let _p = profile::span("PerNs::iter_items"); self.types -- cgit 1.4.1-3-g733a5 From 8c60813096fca9ce5b81bdb22894ca1e1240fdb5 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 15 Aug 2022 17:44:52 +0200 Subject: Fix lowering of empty macro expressions in trailing position --- crates/hir-def/src/body/lower.rs | 10 +++++++++- crates/hir-ty/src/tests/regression.rs | 17 +++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index 66f9c24e872..f6ec8bf7e9e 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -551,9 +551,17 @@ impl ExprCollector<'_> { } } ast::Expr::MacroStmts(e) => { - let statements = e.statements().filter_map(|s| self.collect_stmt(s)).collect(); + let statements: Box<[_]> = + e.statements().filter_map(|s| self.collect_stmt(s)).collect(); let tail = e.expr().map(|e| self.collect_expr(e)); + if e.syntax().children().next().is_none() { + // HACK: make sure that macros that expand to nothing aren't treated as a `()` + // expression when used in block tail position. + cov_mark::hit!(empty_macro_in_trailing_position_is_removed); + return None; + } + self.alloc_expr(Expr::MacroStmts { tail, statements }, syntax_ptr) } ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr), diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs index 93a88ab58ef..1b5ed0603bf 100644 --- a/crates/hir-ty/src/tests/regression.rs +++ b/crates/hir-ty/src/tests/regression.rs @@ -1648,3 +1648,20 @@ fn main() { "#]], ); } + +#[test] +fn trailing_empty_macro() { + cov_mark::check!(empty_macro_in_trailing_position_is_removed); + check_no_mismatches( + r#" +macro_rules! m2 { + ($($t:tt)*) => {$($t)*}; +} + +fn macrostmts() -> u8 { + m2! { 0 } + m2! {} +} + "#, + ); +} -- cgit 1.4.1-3-g733a5 From 91358bd937ff0fdace4371f313fa0cda42d3d81c Mon Sep 17 00:00:00 2001 From: yue4u Date: Tue, 16 Aug 2022 01:24:21 +0900 Subject: fix: format literal lookup --- crates/ide-completion/src/completions/record.rs | 10 +++++----- crates/ide-completion/src/render.rs | 4 +++- crates/ide-completion/src/render/literal.rs | 16 ++++++++++------ crates/ide-completion/src/render/pattern.rs | 18 ++++++++++++------ crates/ide-completion/src/render/union_literal.rs | 9 ++++++--- crates/ide-completion/src/render/variant.rs | 9 +++++++++ crates/ide-completion/src/tests/pattern.rs | 2 +- 7 files changed, 46 insertions(+), 22 deletions(-) diff --git a/crates/ide-completion/src/completions/record.rs b/crates/ide-completion/src/completions/record.rs index bfb98b9f277..5d96fbd30a8 100644 --- a/crates/ide-completion/src/completions/record.rs +++ b/crates/ide-completion/src/completions/record.rs @@ -129,7 +129,7 @@ mod tests { #[test] fn literal_struct_completion_edit() { check_edit( - "FooDesc {…}", + "FooDesc{}", r#" struct FooDesc { pub bar: bool } @@ -154,7 +154,7 @@ fn baz() { #[test] fn literal_struct_impl_self_completion() { check_edit( - "Self {…}", + "Self{}", r#" struct Foo { bar: u64, @@ -180,7 +180,7 @@ impl Foo { ); check_edit( - "Self(…)", + "Self()", r#" mod submod { pub struct Foo(pub u64); @@ -209,7 +209,7 @@ impl submod::Foo { #[test] fn literal_struct_completion_from_sub_modules() { check_edit( - "submod::Struct {…}", + "submod::Struct{}", r#" mod submod { pub struct Struct { @@ -238,7 +238,7 @@ fn f() -> submod::Struct { #[test] fn literal_struct_complexion_module() { check_edit( - "FooDesc {…}", + "FooDesc{}", r#" mod _69latrick { pub struct FooDesc { pub six: bool, pub neuf: Vec, pub bar: bool } diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs index 693007ca307..a2cf6d68e5b 100644 --- a/crates/ide-completion/src/render.rs +++ b/crates/ide-completion/src/render.rs @@ -565,6 +565,7 @@ fn main() { Foo::Fo$0 } kind: SymbolKind( Variant, ), + lookup: "Foo{}", detail: "Foo { x: i32, y: i32 }", }, ] @@ -591,6 +592,7 @@ fn main() { Foo::Fo$0 } kind: SymbolKind( Variant, ), + lookup: "Foo()", detail: "Foo(i32, i32)", }, ] @@ -707,7 +709,7 @@ fn main() { let _: m::Spam = S$0 } kind: SymbolKind( Variant, ), - lookup: "Spam::Bar(…)", + lookup: "Spam::Bar()", detail: "m::Spam::Bar(i32)", relevance: CompletionRelevance { exact_name_match: false, diff --git a/crates/ide-completion/src/render/literal.rs b/crates/ide-completion/src/render/literal.rs index 707dea206be..af9c88a7e0a 100644 --- a/crates/ide-completion/src/render/literal.rs +++ b/crates/ide-completion/src/render/literal.rs @@ -10,8 +10,8 @@ use crate::{ render::{ compute_ref_match, compute_type_match, variant::{ - format_literal_label, render_record_lit, render_tuple_lit, visible_fields, - RenderedLiteral, + format_literal_label, format_literal_lookup, render_record_lit, render_tuple_lit, + visible_fields, RenderedLiteral, }, RenderContext, }, @@ -97,13 +97,20 @@ fn render( if !should_add_parens { kind = StructKind::Unit; } + let label = format_literal_label(&qualified_name, kind); + let lookup = if qualified { + format_literal_lookup(&short_qualified_name.to_string(), kind) + } else { + format_literal_lookup(&qualified_name, kind) + }; let mut item = CompletionItem::new( CompletionItemKind::SymbolKind(thing.symbol_kind()), ctx.source_range(), - format_literal_label(&qualified_name, kind), + label, ); + item.lookup_by(lookup); item.detail(rendered.detail); match snippet_cap { @@ -111,9 +118,6 @@ fn render( None => item.insert_text(rendered.literal), }; - if qualified { - item.lookup_by(format_literal_label(&short_qualified_name.to_string(), kind)); - } item.set_documentation(thing.docs(db)).set_deprecated(thing.is_deprecated(&ctx)); let ty = thing.ty(db); diff --git a/crates/ide-completion/src/render/pattern.rs b/crates/ide-completion/src/render/pattern.rs index 1c1299e33b6..c845ff21aab 100644 --- a/crates/ide-completion/src/render/pattern.rs +++ b/crates/ide-completion/src/render/pattern.rs @@ -8,7 +8,7 @@ use syntax::SmolStr; use crate::{ context::{ParamContext, ParamKind, PathCompletionCtx, PatternContext}, render::{ - variant::{format_literal_label, visible_fields}, + variant::{format_literal_label, format_literal_lookup, visible_fields}, RenderContext, }, CompletionItem, CompletionItemKind, @@ -34,9 +34,10 @@ pub(crate) fn render_struct_pat( let (name, escaped_name) = (name.unescaped().to_smol_str(), name.to_smol_str()); let kind = strukt.kind(ctx.db()); let label = format_literal_label(name.as_str(), kind); + let lookup = format_literal_lookup(name.as_str(), kind); let pat = render_pat(&ctx, pattern_ctx, &escaped_name, kind, &visible_fields, fields_omitted)?; - Some(build_completion(ctx, label, pat, strukt)) + Some(build_completion(ctx, label, lookup, pat, strukt)) } pub(crate) fn render_variant_pat( @@ -60,11 +61,14 @@ pub(crate) fn render_variant_pat( } }; - let (label, pat) = match path_ctx { - Some(PathCompletionCtx { has_call_parens: true, .. }) => (name, escaped_name.to_string()), + let (label, lookup, pat) = match path_ctx { + Some(PathCompletionCtx { has_call_parens: true, .. }) => { + (name.clone(), name, escaped_name.to_string()) + } _ => { let kind = variant.kind(ctx.db()); let label = format_literal_label(name.as_str(), kind); + let lookup = format_literal_lookup(name.as_str(), kind); let pat = render_pat( &ctx, pattern_ctx, @@ -73,16 +77,17 @@ pub(crate) fn render_variant_pat( &visible_fields, fields_omitted, )?; - (label, pat) + (label, lookup, pat) } }; - Some(build_completion(ctx, label, pat, variant)) + Some(build_completion(ctx, label, lookup, pat, variant)) } fn build_completion( ctx: RenderContext<'_>, label: SmolStr, + lookup: SmolStr, pat: String, def: impl HasAttrs + Copy, ) -> CompletionItem { @@ -90,6 +95,7 @@ fn build_completion( item.set_documentation(ctx.docs(def)) .set_deprecated(ctx.is_deprecated(def)) .detail(&pat) + .lookup_by(lookup) .set_relevance(ctx.completion_relevance()); match ctx.snippet_cap() { Some(snippet_cap) => item.insert_snippet(snippet_cap, pat), diff --git a/crates/ide-completion/src/render/union_literal.rs b/crates/ide-completion/src/render/union_literal.rs index bb32330f276..54e97dd57ba 100644 --- a/crates/ide-completion/src/render/union_literal.rs +++ b/crates/ide-completion/src/render/union_literal.rs @@ -6,7 +6,7 @@ use itertools::Itertools; use crate::{ render::{ - variant::{format_literal_label, visible_fields}, + variant::{format_literal_label, format_literal_lookup, visible_fields}, RenderContext, }, CompletionItem, CompletionItemKind, @@ -24,13 +24,16 @@ pub(crate) fn render_union_literal( Some(p) => (p.unescaped().to_string(), p.to_string()), None => (name.unescaped().to_string(), name.to_string()), }; - + let label = format_literal_label(&name.to_smol_str(), StructKind::Record); + let lookup = format_literal_lookup(&name.to_smol_str(), StructKind::Record); let mut item = CompletionItem::new( CompletionItemKind::SymbolKind(SymbolKind::Union), ctx.source_range(), - format_literal_label(&name.to_smol_str(), StructKind::Record), + label, ); + item.lookup_by(lookup); + let fields = un.fields(ctx.db()); let (fields, fields_omitted) = visible_fields(ctx.completion, &fields, un)?; diff --git a/crates/ide-completion/src/render/variant.rs b/crates/ide-completion/src/render/variant.rs index 664845330eb..24e6abdc9ad 100644 --- a/crates/ide-completion/src/render/variant.rs +++ b/crates/ide-completion/src/render/variant.rs @@ -94,3 +94,12 @@ pub(crate) fn format_literal_label(name: &str, kind: StructKind) -> SmolStr { StructKind::Unit => name.into(), } } + +/// Format a struct, etc. literal option for lookup used in completions filtering. +pub(crate) fn format_literal_lookup(name: &str, kind: StructKind) -> SmolStr { + match kind { + StructKind::Tuple => SmolStr::from_iter([name, "()"]), + StructKind::Record => SmolStr::from_iter([name, "{}"]), + StructKind::Unit => name.into(), + } +} diff --git a/crates/ide-completion/src/tests/pattern.rs b/crates/ide-completion/src/tests/pattern.rs index 30ddbe2dc6f..85c4dbd6625 100644 --- a/crates/ide-completion/src/tests/pattern.rs +++ b/crates/ide-completion/src/tests/pattern.rs @@ -467,7 +467,7 @@ fn foo() { fn completes_enum_variant_pat() { cov_mark::check!(enum_variant_pattern_path); check_edit( - "RecordVariant {…}", + "RecordVariant{}", r#" enum Enum { RecordVariant { field: u32 } -- cgit 1.4.1-3-g733a5 From 4a5c46fb02b9124dc0bd5bafaccbd5a41121437e Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 15 Aug 2022 18:29:43 +0200 Subject: Manually implement Debug for ImportKind. --- compiler/rustc_resolve/src/imports.rs | 40 ++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index b89273990d8..9c2539d08d8 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -31,7 +31,7 @@ use std::{mem, ptr}; type Res = def::Res; /// Contains data for specific kinds of imports. -#[derive(Clone, Debug)] +#[derive(Clone)] pub enum ImportKind<'a> { Single { /// `source` in `use prefix::source as target`. @@ -62,6 +62,44 @@ pub enum ImportKind<'a> { MacroUse, } +/// Manually implement `Debug` for `ImportKind` because the `source/target_bindings` +/// contain `Cell`s which can introduce infinite loops while printing. +impl<'a> std::fmt::Debug for ImportKind<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + use ImportKind::*; + match self { + Single { + ref source, + ref target, + ref type_ns_only, + ref nested, + ref additional_ids, + // Ignore the following to avoid an infinite loop while printing. + source_bindings: _, + target_bindings: _, + } => f + .debug_struct("Single") + .field("source", source) + .field("target", target) + .field("type_ns_only", type_ns_only) + .field("nested", nested) + .field("additional_ids", additional_ids) + .finish(), + Glob { ref is_prelude, ref max_vis } => f + .debug_struct("Glob") + .field("is_prelude", is_prelude) + .field("max_vis", max_vis) + .finish(), + ExternCrate { ref source, ref target } => f + .debug_struct("ExternCrate") + .field("source", source) + .field("target", target) + .finish(), + MacroUse => f.debug_struct("MacroUse").finish(), + } + } +} + /// One import. #[derive(Debug, Clone)] pub(crate) struct Import<'a> { -- cgit 1.4.1-3-g733a5 From 03db9199890801b8098954d5d6b620fcbef8443d Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Tue, 16 Aug 2022 03:08:25 +0900 Subject: remove unnecessary stderr files --- .../higher-ranked-projection.badbase.stderr | 17 ----------------- .../higher-ranked-projection.badnll.stderr | 2 -- .../ui/lub-glb/old-lub-glb-hr-noteq1.nllleak.stderr | 2 -- .../ui/lub-glb/old-lub-glb-hr-noteq1.nllnoleak.stderr | 2 -- 4 files changed, 23 deletions(-) delete mode 100644 src/test/ui/associated-types/higher-ranked-projection.badbase.stderr delete mode 100644 src/test/ui/associated-types/higher-ranked-projection.badnll.stderr delete mode 100644 src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllleak.stderr delete mode 100644 src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllnoleak.stderr diff --git a/src/test/ui/associated-types/higher-ranked-projection.badbase.stderr b/src/test/ui/associated-types/higher-ranked-projection.badbase.stderr deleted file mode 100644 index 8b2b87223a5..00000000000 --- a/src/test/ui/associated-types/higher-ranked-projection.badbase.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/higher-ranked-projection.rs:25:5 - | -LL | foo(()); - | ^^^^^^^ one type is more general than the other - | - = note: expected reference `&'a ()` - found reference `&()` -note: the lifetime requirement is introduced here - --> $DIR/higher-ranked-projection.rs:16:33 - | -LL | where for<'a> &'a T: Mirror - | ^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/associated-types/higher-ranked-projection.badnll.stderr b/src/test/ui/associated-types/higher-ranked-projection.badnll.stderr deleted file mode 100644 index 217392aa35b..00000000000 --- a/src/test/ui/associated-types/higher-ranked-projection.badnll.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: unknown debugging option: `borrowck` - diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllleak.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllleak.stderr deleted file mode 100644 index 217392aa35b..00000000000 --- a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllleak.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: unknown debugging option: `borrowck` - diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllnoleak.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllnoleak.stderr deleted file mode 100644 index 217392aa35b..00000000000 --- a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllnoleak.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: unknown debugging option: `borrowck` - -- cgit 1.4.1-3-g733a5 From 611221d8aee134eb99749045e05896352550639c Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Mon, 15 Aug 2022 20:51:32 +0200 Subject: Update compiler/rustc_resolve/src/imports.rs --- compiler/rustc_resolve/src/imports.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 9c2539d08d8..e0d57ded5bf 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -84,7 +84,7 @@ impl<'a> std::fmt::Debug for ImportKind<'a> { .field("type_ns_only", type_ns_only) .field("nested", nested) .field("additional_ids", additional_ids) - .finish(), + .finish_non_exhaustive(), Glob { ref is_prelude, ref max_vis } => f .debug_struct("Glob") .field("is_prelude", is_prelude) -- cgit 1.4.1-3-g733a5 From fd934c99bcf1a930ef44a27129ef24b323d3c54f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 21 Jul 2022 22:00:15 +0000 Subject: Do not allow Drop impl on foreign fundamental types --- .../rustc_error_messages/locales/en-US/typeck.ftl | 4 ++-- compiler/rustc_typeck/src/coherence/builtin.rs | 8 +++++--- src/test/ui/drop/drop-foreign-fundamental.rs | 23 ++++++++++++++++++++++ src/test/ui/drop/drop-foreign-fundamental.stderr | 9 +++++++++ src/test/ui/dropck/drop-on-non-struct.rs | 7 +++---- src/test/ui/dropck/drop-on-non-struct.stderr | 4 ++-- src/test/ui/error-codes/E0117.rs | 2 +- src/test/ui/error-codes/E0117.stderr | 4 ++-- src/test/ui/error-codes/E0120.stderr | 4 ++-- src/test/ui/issues/issue-41974.stderr | 4 ++-- 10 files changed, 51 insertions(+), 18 deletions(-) create mode 100644 src/test/ui/drop/drop-foreign-fundamental.rs create mode 100644 src/test/ui/drop/drop-foreign-fundamental.stderr diff --git a/compiler/rustc_error_messages/locales/en-US/typeck.ftl b/compiler/rustc_error_messages/locales/en-US/typeck.ftl index 494b8f91393..2a8488cc548 100644 --- a/compiler/rustc_error_messages/locales/en-US/typeck.ftl +++ b/compiler/rustc_error_messages/locales/en-US/typeck.ftl @@ -24,8 +24,8 @@ typeck_lifetimes_or_bounds_mismatch_on_trait = .generics_label = lifetimes in impl do not match this {$item_kind} in trait typeck_drop_impl_on_wrong_item = - the `Drop` trait may only be implemented for structs, enums, and unions - .label = must be a struct, enum, or union + the `Drop` trait may only be implemented for local structs, enums, and unions + .label = must be a struct, enum, or union in the current crate typeck_field_already_declared = field `{$field_name}` is already declared diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs index 043e21fc1e3..2467a81638f 100644 --- a/compiler/rustc_typeck/src/coherence/builtin.rs +++ b/compiler/rustc_typeck/src/coherence/builtin.rs @@ -47,9 +47,11 @@ impl<'tcx> Checker<'tcx> { } fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) { - // Destructors only work on nominal types. - if let ty::Adt(..) | ty::Error(_) = tcx.type_of(impl_did).kind() { - return; + // Destructors only work on local ADT types. + match tcx.type_of(impl_did).kind() { + ty::Adt(def, _) if def.did().is_local() => return, + ty::Error(_) => return, + _ => {} } let sp = match tcx.hir().expect_item(impl_did).kind { diff --git a/src/test/ui/drop/drop-foreign-fundamental.rs b/src/test/ui/drop/drop-foreign-fundamental.rs new file mode 100644 index 00000000000..c43df40d6c2 --- /dev/null +++ b/src/test/ui/drop/drop-foreign-fundamental.rs @@ -0,0 +1,23 @@ +use std::ops::Deref; +use std::pin::Pin; + +struct Whatever(T); + +impl Deref for Whatever { + type Target = T; + + fn deref(&self) -> &T { + &self.0 + } +} + +struct A; + +impl Drop for Pin> { + //~^ ERROR the `Drop` trait may only be implemented for local structs, enums, and unions + fn drop(&mut self) {} +} + +fn main() { + let x = Pin::new(Whatever(1.0f32)); +} diff --git a/src/test/ui/drop/drop-foreign-fundamental.stderr b/src/test/ui/drop/drop-foreign-fundamental.stderr new file mode 100644 index 00000000000..fbd1ba08591 --- /dev/null +++ b/src/test/ui/drop/drop-foreign-fundamental.stderr @@ -0,0 +1,9 @@ +error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions + --> $DIR/drop-foreign-fundamental.rs:16:15 + | +LL | impl Drop for Pin> { + | ^^^^^^^^^^^^^^^^ must be a struct, enum, or union in the current crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0120`. diff --git a/src/test/ui/dropck/drop-on-non-struct.rs b/src/test/ui/dropck/drop-on-non-struct.rs index ef5e18126dc..145eab126c2 100644 --- a/src/test/ui/dropck/drop-on-non-struct.rs +++ b/src/test/ui/dropck/drop-on-non-struct.rs @@ -1,5 +1,5 @@ impl<'a> Drop for &'a mut isize { - //~^ ERROR the `Drop` trait may only be implemented for structs, enums, and unions + //~^ ERROR the `Drop` trait may only be implemented for local structs, enums, and unions //~^^ ERROR E0117 fn drop(&mut self) { println!("kaboom"); @@ -8,8 +8,7 @@ impl<'a> Drop for &'a mut isize { impl Drop for Nonexistent { //~^ ERROR cannot find type `Nonexistent` - fn drop(&mut self) { } + fn drop(&mut self) {} } -fn main() { -} +fn main() {} diff --git a/src/test/ui/dropck/drop-on-non-struct.stderr b/src/test/ui/dropck/drop-on-non-struct.stderr index e52728f3781..e8fbe5e9726 100644 --- a/src/test/ui/dropck/drop-on-non-struct.stderr +++ b/src/test/ui/dropck/drop-on-non-struct.stderr @@ -15,11 +15,11 @@ LL | impl<'a> Drop for &'a mut isize { | = note: define and implement a trait or new type instead -error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions +error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions --> $DIR/drop-on-non-struct.rs:1:19 | LL | impl<'a> Drop for &'a mut isize { - | ^^^^^^^^^^^^^ must be a struct, enum, or union + | ^^^^^^^^^^^^^ must be a struct, enum, or union in the current crate error: aborting due to 3 previous errors diff --git a/src/test/ui/error-codes/E0117.rs b/src/test/ui/error-codes/E0117.rs index 22b48657385..406d24e3666 100644 --- a/src/test/ui/error-codes/E0117.rs +++ b/src/test/ui/error-codes/E0117.rs @@ -1,4 +1,4 @@ impl Drop for u32 {} //~ ERROR E0117 -//~| ERROR the `Drop` trait may only be implemented for structs, enums, and unions +//~| ERROR the `Drop` trait may only be implemented for local structs, enums, and unions fn main() {} diff --git a/src/test/ui/error-codes/E0117.stderr b/src/test/ui/error-codes/E0117.stderr index 76d9f5cc0e5..f144aa9f72c 100644 --- a/src/test/ui/error-codes/E0117.stderr +++ b/src/test/ui/error-codes/E0117.stderr @@ -9,11 +9,11 @@ LL | impl Drop for u32 {} | = note: define and implement a trait or new type instead -error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions +error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions --> $DIR/E0117.rs:1:15 | LL | impl Drop for u32 {} - | ^^^ must be a struct, enum, or union + | ^^^ must be a struct, enum, or union in the current crate error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/E0120.stderr b/src/test/ui/error-codes/E0120.stderr index 6c306455e42..75778f1f94a 100644 --- a/src/test/ui/error-codes/E0120.stderr +++ b/src/test/ui/error-codes/E0120.stderr @@ -1,8 +1,8 @@ -error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions +error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions --> $DIR/E0120.rs:3:15 | LL | impl Drop for dyn MyTrait { - | ^^^^^^^^^^^ must be a struct, enum, or union + | ^^^^^^^^^^^ must be a struct, enum, or union in the current crate error: aborting due to previous error diff --git a/src/test/ui/issues/issue-41974.stderr b/src/test/ui/issues/issue-41974.stderr index fcbb4014025..e249db9df53 100644 --- a/src/test/ui/issues/issue-41974.stderr +++ b/src/test/ui/issues/issue-41974.stderr @@ -7,11 +7,11 @@ LL | impl Drop for T where T: A { = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local = note: only traits defined in the current crate can be implemented for a type parameter -error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions +error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions --> $DIR/issue-41974.rs:7:18 | LL | impl Drop for T where T: A { - | ^ must be a struct, enum, or union + | ^ must be a struct, enum, or union in the current crate error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From e37565d2db8d7cf92a6d1df535343d4b2881fc35 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 16 Aug 2022 03:02:04 +0000 Subject: Make as_ref suggestion a note --- compiler/rustc_borrowck/src/diagnostics/mod.rs | 14 ++++---- .../borrowck/suggest-as-ref-on-mut-closure.stderr | 5 +-- src/test/ui/suggestions/as-ref-2.fixed | 13 -------- src/test/ui/suggestions/as-ref-2.rs | 2 -- src/test/ui/suggestions/as-ref-2.stderr | 10 +++--- src/test/ui/suggestions/option-content-move.fixed | 39 ---------------------- src/test/ui/suggestions/option-content-move.rs | 2 -- src/test/ui/suggestions/option-content-move.stderr | 14 +++----- 8 files changed, 15 insertions(+), 84 deletions(-) delete mode 100644 src/test/ui/suggestions/as-ref-2.fixed delete mode 100644 src/test/ui/suggestions/option-content-move.fixed diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index cc5a3e16c96..683084cf09d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -1086,14 +1086,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ), ); } - if is_option_or_result && maybe_reinitialized_locations_is_empty { - err.span_suggestion_verbose( - fn_call_span.shrink_to_lo(), - "consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents", - "as_ref().", - Applicability::MachineApplicable, - ); - } // Avoid pointing to the same function in multiple different // error messages. if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) { @@ -1102,6 +1094,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &format!("this function takes ownership of the receiver `self`, which moves {}", place_name) ); } + if is_option_or_result && maybe_reinitialized_locations_is_empty { + err.span_label( + var_span, + "help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents", + ); + } } // Other desugarings takes &self, which cannot cause a move _ => {} diff --git a/src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr b/src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr index 17546f73836..b1af090aec2 100644 --- a/src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr +++ b/src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr @@ -5,6 +5,7 @@ LL | cb.map(|cb| cb()); | ^^^-------------- | | | | | `*cb` moved due to this method call + | help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents | move occurs because `*cb` has type `Option<&mut dyn FnMut()>`, which does not implement the `Copy` trait | note: this function takes ownership of the receiver `self`, which moves `*cb` @@ -12,10 +13,6 @@ note: this function takes ownership of the receiver `self`, which moves `*cb` | LL | pub const fn map(self, f: F) -> Option | ^^^^ -help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents - | -LL | cb.as_ref().map(|cb| cb()); - | +++++++++ error[E0596]: cannot borrow `*cb` as mutable, as it is behind a `&` reference --> $DIR/suggest-as-ref-on-mut-closure.rs:12:26 diff --git a/src/test/ui/suggestions/as-ref-2.fixed b/src/test/ui/suggestions/as-ref-2.fixed deleted file mode 100644 index 13bbb233f39..00000000000 --- a/src/test/ui/suggestions/as-ref-2.fixed +++ /dev/null @@ -1,13 +0,0 @@ -// run-rustfix - -struct Struct; - -fn bar(_: &Struct) -> Struct { - Struct -} - -fn main() { - let foo = Some(Struct); - let _x: Option = foo.as_ref().map(|s| bar(&s)); - let _y = foo; //~ERROR use of moved value: `foo` -} diff --git a/src/test/ui/suggestions/as-ref-2.rs b/src/test/ui/suggestions/as-ref-2.rs index 74d61cdd95f..b22f409b44a 100644 --- a/src/test/ui/suggestions/as-ref-2.rs +++ b/src/test/ui/suggestions/as-ref-2.rs @@ -1,5 +1,3 @@ -// run-rustfix - struct Struct; fn bar(_: &Struct) -> Struct { diff --git a/src/test/ui/suggestions/as-ref-2.stderr b/src/test/ui/suggestions/as-ref-2.stderr index 08b9fb1abd7..e15e45d86b9 100644 --- a/src/test/ui/suggestions/as-ref-2.stderr +++ b/src/test/ui/suggestions/as-ref-2.stderr @@ -1,10 +1,12 @@ error[E0382]: use of moved value: `foo` - --> $DIR/as-ref-2.rs:12:14 + --> $DIR/as-ref-2.rs:10:14 | LL | let foo = Some(Struct); | --- move occurs because `foo` has type `Option`, which does not implement the `Copy` trait LL | let _x: Option = foo.map(|s| bar(&s)); - | ---------------- `foo` moved due to this method call + | --- ---------------- `foo` moved due to this method call + | | + | help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents LL | let _y = foo; | ^^^ value used here after move | @@ -13,10 +15,6 @@ note: this function takes ownership of the receiver `self`, which moves `foo` | LL | pub const fn map(self, f: F) -> Option | ^^^^ -help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents - | -LL | let _x: Option = foo.as_ref().map(|s| bar(&s)); - | +++++++++ error: aborting due to previous error diff --git a/src/test/ui/suggestions/option-content-move.fixed b/src/test/ui/suggestions/option-content-move.fixed deleted file mode 100644 index ba16bcc8a33..00000000000 --- a/src/test/ui/suggestions/option-content-move.fixed +++ /dev/null @@ -1,39 +0,0 @@ -//run-rustfix - -pub struct LipogramCorpora { - selections: Vec<(char, Option)>, -} - -impl LipogramCorpora { - pub fn validate_all(&mut self) -> Result<(), char> { - for selection in &self.selections { - if selection.1.is_some() { - if selection.1.as_ref().unwrap().contains(selection.0) { - //~^ ERROR cannot move out of `selection.1` - return Err(selection.0); - } - } - } - Ok(()) - } -} - -pub struct LipogramCorpora2 { - selections: Vec<(char, Result)>, -} - -impl LipogramCorpora2 { - pub fn validate_all(&mut self) -> Result<(), char> { - for selection in &self.selections { - if selection.1.is_ok() { - if selection.1.as_ref().unwrap().contains(selection.0) { - //~^ ERROR cannot move out of `selection.1` - return Err(selection.0); - } - } - } - Ok(()) - } -} - -fn main() {} diff --git a/src/test/ui/suggestions/option-content-move.rs b/src/test/ui/suggestions/option-content-move.rs index ef38f114eca..46c895b95f5 100644 --- a/src/test/ui/suggestions/option-content-move.rs +++ b/src/test/ui/suggestions/option-content-move.rs @@ -1,5 +1,3 @@ -//run-rustfix - pub struct LipogramCorpora { selections: Vec<(char, Option)>, } diff --git a/src/test/ui/suggestions/option-content-move.stderr b/src/test/ui/suggestions/option-content-move.stderr index d008971e438..a6f1ebc975f 100644 --- a/src/test/ui/suggestions/option-content-move.stderr +++ b/src/test/ui/suggestions/option-content-move.stderr @@ -1,9 +1,10 @@ error[E0507]: cannot move out of `selection.1` which is behind a shared reference - --> $DIR/option-content-move.rs:11:20 + --> $DIR/option-content-move.rs:9:20 | LL | if selection.1.unwrap().contains(selection.0) { | ^^^^^^^^^^^ -------- `selection.1` moved due to this method call | | + | help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents | move occurs because `selection.1` has type `Option`, which does not implement the `Copy` trait | note: this function takes ownership of the receiver `self`, which moves `selection.1` @@ -11,17 +12,14 @@ note: this function takes ownership of the receiver `self`, which moves `selecti | LL | pub const fn unwrap(self) -> T { | ^^^^ -help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents - | -LL | if selection.1.as_ref().unwrap().contains(selection.0) { - | +++++++++ error[E0507]: cannot move out of `selection.1` which is behind a shared reference - --> $DIR/option-content-move.rs:29:20 + --> $DIR/option-content-move.rs:27:20 | LL | if selection.1.unwrap().contains(selection.0) { | ^^^^^^^^^^^ -------- `selection.1` moved due to this method call | | + | help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents | move occurs because `selection.1` has type `Result`, which does not implement the `Copy` trait | note: this function takes ownership of the receiver `self`, which moves `selection.1` @@ -29,10 +27,6 @@ note: this function takes ownership of the receiver `self`, which moves `selecti | LL | pub fn unwrap(self) -> T | ^^^^ -help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents - | -LL | if selection.1.as_ref().unwrap().contains(selection.0) { - | +++++++++ error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From fb62f2804fd9de510f1af6277641e5c5573df1c7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 16 Aug 2022 13:50:18 +0200 Subject: Update minifier version to 0.2.2 --- Cargo.lock | 4 ++-- src/librustdoc/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 395f5a127bd..d027707fd85 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2415,9 +2415,9 @@ dependencies = [ [[package]] name = "minifier" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac96d1e7a65f206443f95afff6de8f1690c77c97d6fc9c9bb2d2cd0662e9ff9f" +checksum = "8eb022374af2f446981254e6bf9efb6e2c9e1a53176d395fca02792fd4435729" [[package]] name = "minimal-lexical" diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index ddaa7438e17..cbdfea89efb 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -11,7 +11,7 @@ arrayvec = { version = "0.7", default-features = false } askama = { version = "0.11", default-features = false, features = ["config"] } atty = "0.2" pulldown-cmark = { version = "0.9.2", default-features = false } -minifier = "0.2.1" +minifier = "0.2.2" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" smallvec = "1.8.1" -- cgit 1.4.1-3-g733a5 From 25de53f76842544b695f826303034fd0419a5d6a Mon Sep 17 00:00:00 2001 From: Raoul Strackx Date: Wed, 10 Aug 2022 10:46:27 +0200 Subject: Refactor copying data to userspace --- library/std/src/sys/sgx/abi/usercalls/alloc.rs | 51 ++++++++++++++++---------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/library/std/src/sys/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/sgx/abi/usercalls/alloc.rs index 66fa1efbf10..a3b90fc7d80 100644 --- a/library/std/src/sys/sgx/abi/usercalls/alloc.rs +++ b/library/std/src/sys/sgx/abi/usercalls/alloc.rs @@ -305,6 +305,34 @@ where } } +// Split a memory region ptr..ptr + len into three parts: +// +--------+ +// | small0 | Chunk smaller than 8 bytes +// +--------+ +// | big | Chunk 8-byte aligned, and size a multiple of 8 bytes +// +--------+ +// | small1 | Chunk smaller than 8 bytes +// +--------+ +fn region_as_aligned_chunks(ptr: *const u8, len: usize) -> (u8, usize, u8) { + let small0_size = (8 - ptr as usize % 8) as u8; + let small1_size = ((len - small0_size as usize) % 8) as u8; + let big_size = len - small0_size as usize - small1_size as usize; + + (small0_size, big_size, small1_size) +} + +unsafe fn copy_quadwords(src: *const u8, dst: *mut u8, len: usize) { + unsafe { + asm!( + "rep movsq (%rsi), (%rdi)", + inout("rcx") len / 8 => _, + inout("rdi") dst => _, + inout("rsi") src => _, + options(att_syntax, nostack, preserves_flags) + ); + } +} + /// Copies `len` bytes of data from enclave pointer `src` to userspace `dst` /// /// This function mitigates stale data vulnerabilities by ensuring all writes to untrusted memory are either: @@ -343,17 +371,6 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize) } } - unsafe fn copy_aligned_quadwords_to_userspace(src: *const u8, dst: *mut u8, len: usize) { - unsafe { - asm!( - "rep movsq (%rsi), (%rdi)", - inout("rcx") len / 8 => _, - inout("rdi") dst => _, - inout("rsi") src => _, - options(att_syntax, nostack, preserves_flags) - ); - } - } assert!(!src.is_null()); assert!(!dst.is_null()); assert!(is_enclave_range(src, len)); @@ -370,7 +387,7 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize) } else if len % 8 == 0 && dst as usize % 8 == 0 { // Copying 8-byte aligned quadwords: copy quad word per quad word unsafe { - copy_aligned_quadwords_to_userspace(src, dst, len); + copy_quadwords(src, dst, len); } } else { // Split copies into three parts: @@ -381,20 +398,16 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize) // +--------+ // | small1 | Chunk smaller than 8 bytes // +--------+ + let (small0_size, big_size, small1_size) = region_as_aligned_chunks(dst, len); unsafe { // Copy small0 - let small0_size = (8 - dst as usize % 8) as u8; - let small0_src = src; - let small0_dst = dst; - copy_bytewise_to_userspace(small0_src as _, small0_dst, small0_size as _); + copy_bytewise_to_userspace(src, dst, small0_size as _); // Copy big - let small1_size = ((len - small0_size as usize) % 8) as u8; - let big_size = len - small0_size as usize - small1_size as usize; let big_src = src.offset(small0_size as _); let big_dst = dst.offset(small0_size as _); - copy_aligned_quadwords_to_userspace(big_src as _, big_dst, big_size); + copy_quadwords(big_src as _, big_dst, big_size); // Copy small1 let small1_src = src.offset(big_size as isize + small0_size as isize); -- cgit 1.4.1-3-g733a5 From 14db0809335f51e5f239682d63895866f4ebdb8c Mon Sep 17 00:00:00 2001 From: Aleksandr Pak Date: Tue, 16 Aug 2022 17:06:32 +0300 Subject: feat: add inline_type_alias_uses assist --- .../ide-assists/src/handlers/inline_type_alias.rs | 234 ++++++++++++++++++--- crates/ide-assists/src/lib.rs | 1 + crates/ide-assists/src/tests/generated.rs | 25 +++ 3 files changed, 227 insertions(+), 33 deletions(-) diff --git a/crates/ide-assists/src/handlers/inline_type_alias.rs b/crates/ide-assists/src/handlers/inline_type_alias.rs index 054663a06a1..6b1cf9b90dc 100644 --- a/crates/ide-assists/src/handlers/inline_type_alias.rs +++ b/crates/ide-assists/src/handlers/inline_type_alias.rs @@ -1,9 +1,9 @@ // Some ideas for future improvements: // - Support replacing aliases which are used in expressions, e.g. `A::new()`. -// - "inline_alias_to_users" assist #10881. // - Remove unused aliases if there are no longer any users, see inline_call.rs. use hir::{HasSource, PathResolution}; +use ide_db::{defs::Definition, search::FileReference}; use itertools::Itertools; use std::collections::HashMap; use syntax::{ @@ -16,6 +16,78 @@ use crate::{ AssistId, AssistKind, }; +// Assist: inline_type_alias_uses +// +// Inline a type alias into all of its uses where possible. +// +// ``` +// type $0A = i32; +// fn id(x: A) -> A { +// x +// }; +// fn foo() { +// let _: A = 3; +// } +// ``` +// -> +// ``` +// type A = i32; +// fn id(x: i32) -> i32 { +// x +// }; +// fn foo() { +// let _: i32 = 3; +// } +pub(crate) fn inline_type_alias_uses(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let name = ctx.find_node_at_offset::()?; + let ast_alias = name.syntax().parent().and_then(ast::TypeAlias::cast)?; + + let hir_alias = ctx.sema.to_def(&ast_alias)?; + let concrete_type = ast_alias.ty()?; + + let usages = Definition::TypeAlias(hir_alias).usages(&ctx.sema); + if !usages.at_least_one() { + return None; + } + + // until this is ok + + acc.add( + AssistId("inline_type_alias_uses", AssistKind::RefactorInline), + "Inline type alias into all uses", + name.syntax().text_range(), + |builder| { + let usages = usages.all(); + + let mut inline_refs_for_file = |file_id, refs: Vec| { + builder.edit_file(file_id); + + let path_types: Vec = refs + .into_iter() + .filter_map(|file_ref| match file_ref.name { + ast::NameLike::NameRef(path_type) => { + path_type.syntax().ancestors().find_map(ast::PathType::cast) + } + _ => None, + }) + .collect(); + + for (target, replacement) in path_types.into_iter().filter_map(|path_type| { + let replacement = inline(&ast_alias, &path_type)?.to_text(&concrete_type); + let target = path_type.syntax().text_range(); + Some((target, replacement)) + }) { + builder.replace(target, replacement); + } + }; + + for (file_id, refs) in usages.into_iter() { + inline_refs_for_file(file_id, refs); + } + }, + ) +} + // Assist: inline_type_alias // // Replace a type alias with its concrete type. @@ -36,11 +108,6 @@ use crate::{ // } // ``` pub(crate) fn inline_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { - enum Replacement { - Generic { lifetime_map: LifetimeMap, const_and_type_map: ConstAndTypeMap }, - Plain, - } - let alias_instance = ctx.find_node_at_offset::()?; let concrete_type; let replacement; @@ -59,23 +126,7 @@ pub(crate) fn inline_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) -> O _ => { let alias = get_type_alias(&ctx, &alias_instance)?; concrete_type = alias.ty()?; - - replacement = if let Some(alias_generics) = alias.generic_param_list() { - if alias_generics.generic_params().next().is_none() { - cov_mark::hit!(no_generics_params); - return None; - } - - let instance_args = - alias_instance.syntax().descendants().find_map(ast::GenericArgList::cast); - - Replacement::Generic { - lifetime_map: LifetimeMap::new(&instance_args, &alias_generics)?, - const_and_type_map: ConstAndTypeMap::new(&instance_args, &alias_generics)?, - } - } else { - Replacement::Plain - }; + replacement = inline(&alias, &alias_instance)?; } } @@ -85,19 +136,45 @@ pub(crate) fn inline_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) -> O AssistId("inline_type_alias", AssistKind::RefactorInline), "Inline type alias", target, - |builder| { - let replacement_text = match replacement { - Replacement::Generic { lifetime_map, const_and_type_map } => { - create_replacement(&lifetime_map, &const_and_type_map, &concrete_type) - } - Replacement::Plain => concrete_type.to_string(), - }; - - builder.replace(target, replacement_text); - }, + |builder| builder.replace(target, replacement.to_text(&concrete_type)), ) } +impl Replacement { + fn to_text(&self, concrete_type: &ast::Type) -> String { + match self { + Replacement::Generic { lifetime_map, const_and_type_map } => { + create_replacement(&lifetime_map, &const_and_type_map, &concrete_type) + } + Replacement::Plain => concrete_type.to_string(), + } + } +} + +enum Replacement { + Generic { lifetime_map: LifetimeMap, const_and_type_map: ConstAndTypeMap }, + Plain, +} + +fn inline(alias_def: &ast::TypeAlias, alias_instance: &ast::PathType) -> Option { + let repl = if let Some(alias_generics) = alias_def.generic_param_list() { + if alias_generics.generic_params().next().is_none() { + cov_mark::hit!(no_generics_params); + return None; + } + let instance_args = + alias_instance.syntax().descendants().find_map(ast::GenericArgList::cast); + + Replacement::Generic { + lifetime_map: LifetimeMap::new(&instance_args, &alias_generics)?, + const_and_type_map: ConstAndTypeMap::new(&instance_args, &alias_generics)?, + } + } else { + Replacement::Plain + }; + Some(repl) +} + struct LifetimeMap(HashMap); impl LifetimeMap { @@ -835,4 +912,95 @@ trait Tr { "#, ); } + + mod inline_type_alias_uses { + use crate::{handlers::inline_type_alias::inline_type_alias_uses, tests::check_assist}; + + #[test] + fn inline_uses() { + check_assist( + inline_type_alias_uses, + r#" +type $0A = u32; + +fn foo() { + let _: A = 3; + let _: A = 4; +} +"#, + r#" +type A = u32; + +fn foo() { + let _: u32 = 3; + let _: u32 = 4; +} +"#, + ); + } + + #[test] + fn inline_uses_across_files() { + check_assist( + inline_type_alias_uses, + r#" +//- /lib.rs +mod foo; +type $0T = Vec; +fn f() -> T<&str> { + vec!["hello"] +} + +//- /foo.rs +use super::T; +fn foo() { + let _: T = Vec::new(); +} +"#, + r#" +//- /lib.rs +mod foo; +type T = Vec; +fn f() -> Vec<&str> { + vec!["hello"] +} + +//- /foo.rs +use super::T; +fn foo() { + let _: Vec = Vec::new(); +} +"#, + ); + } + + #[test] + fn inline_uses_across_files_fails() { + check_assist( + inline_type_alias_uses, + r#" +//- /lib.rs +mod foo; +type $0I = i32; + +//- /foo.rs +use super::I; +fn foo() { + let _: I = 0; +} +"#, + r#" +//- /lib.rs +mod foo; +type I = i32; + +//- /foo.rs +use super::I; +fn foo() { + let _: i32 = 0; +} +"#, + ); + } + } } diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs index fe87aa15fcf..7fb35143fa2 100644 --- a/crates/ide-assists/src/lib.rs +++ b/crates/ide-assists/src/lib.rs @@ -243,6 +243,7 @@ mod handlers { inline_call::inline_into_callers, inline_local_variable::inline_local_variable, inline_type_alias::inline_type_alias, + inline_type_alias::inline_type_alias_uses, introduce_named_generic::introduce_named_generic, introduce_named_lifetime::introduce_named_lifetime, invert_if::invert_if, diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs index 6eaab48a32b..22319f36134 100644 --- a/crates/ide-assists/src/tests/generated.rs +++ b/crates/ide-assists/src/tests/generated.rs @@ -1356,6 +1356,31 @@ fn main() { ) } +#[test] +fn doctest_inline_type_alias_uses() { + check_doc_test( + "inline_type_alias_uses", + r#####" +type $0A = i32; +fn id(x: A) -> A { + x +}; +fn foo() { + let _: A = 3; +} +"#####, + r#####" +type A = i32; +fn id(x: i32) -> i32 { + x +}; +fn foo() { + let _: i32 = 3; +} +"#####, + ) +} + #[test] fn doctest_introduce_named_generic() { check_doc_test( -- cgit 1.4.1-3-g733a5 From 0616cee92b47b539a802171f7e6817663175502d Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 16 Aug 2022 16:51:40 +0200 Subject: Add a setting for keyword hover popups --- crates/ide/src/hover.rs | 1 + crates/ide/src/hover/render.rs | 2 +- crates/ide/src/hover/tests.rs | 42 +++++++++++++++++++++++++++++++------- crates/ide/src/static_index.rs | 7 +++++-- crates/rust-analyzer/src/config.rs | 4 ++++ docs/user/generated_config.adoc | 6 ++++++ editors/code/package.json | 5 +++++ 7 files changed, 57 insertions(+), 10 deletions(-) diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index fa2c6f09ab4..3687b597fc6 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -27,6 +27,7 @@ use crate::{ pub struct HoverConfig { pub links_in_hover: bool, pub documentation: Option, + pub keywords: bool, } impl HoverConfig { diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index 6c50a4e6adc..d52adaee535 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -230,7 +230,7 @@ pub(super) fn keyword( config: &HoverConfig, token: &SyntaxToken, ) -> Option { - if !token.kind().is_keyword() || !config.documentation.is_some() { + if !token.kind().is_keyword() || !config.documentation.is_some() || !config.keywords { return None; } let parent = token.parent()?; diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index c6274264b8f..685eb4521eb 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -8,7 +8,11 @@ fn check_hover_no_result(ra_fixture: &str) { let (analysis, position) = fixture::position(ra_fixture); let hover = analysis .hover( - &HoverConfig { links_in_hover: true, documentation: Some(HoverDocFormat::Markdown) }, + &HoverConfig { + links_in_hover: true, + documentation: Some(HoverDocFormat::Markdown), + keywords: true, + }, FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) }, ) .unwrap(); @@ -20,7 +24,11 @@ fn check(ra_fixture: &str, expect: Expect) { let (analysis, position) = fixture::position(ra_fixture); let hover = analysis .hover( - &HoverConfig { links_in_hover: true, documentation: Some(HoverDocFormat::Markdown) }, + &HoverConfig { + links_in_hover: true, + documentation: Some(HoverDocFormat::Markdown), + keywords: true, + }, FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) }, ) .unwrap() @@ -37,7 +45,11 @@ fn check_hover_no_links(ra_fixture: &str, expect: Expect) { let (analysis, position) = fixture::position(ra_fixture); let hover = analysis .hover( - &HoverConfig { links_in_hover: false, documentation: Some(HoverDocFormat::Markdown) }, + &HoverConfig { + links_in_hover: false, + documentation: Some(HoverDocFormat::Markdown), + keywords: true, + }, FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) }, ) .unwrap() @@ -54,7 +66,11 @@ fn check_hover_no_markdown(ra_fixture: &str, expect: Expect) { let (analysis, position) = fixture::position(ra_fixture); let hover = analysis .hover( - &HoverConfig { links_in_hover: true, documentation: Some(HoverDocFormat::PlainText) }, + &HoverConfig { + links_in_hover: true, + documentation: Some(HoverDocFormat::PlainText), + keywords: true, + }, FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) }, ) .unwrap() @@ -71,7 +87,11 @@ fn check_actions(ra_fixture: &str, expect: Expect) { let (analysis, file_id, position) = fixture::range_or_position(ra_fixture); let hover = analysis .hover( - &HoverConfig { links_in_hover: true, documentation: Some(HoverDocFormat::Markdown) }, + &HoverConfig { + links_in_hover: true, + documentation: Some(HoverDocFormat::Markdown), + keywords: true, + }, FileRange { file_id, range: position.range_or_empty() }, ) .unwrap() @@ -83,7 +103,11 @@ fn check_hover_range(ra_fixture: &str, expect: Expect) { let (analysis, range) = fixture::range(ra_fixture); let hover = analysis .hover( - &HoverConfig { links_in_hover: false, documentation: Some(HoverDocFormat::Markdown) }, + &HoverConfig { + links_in_hover: false, + documentation: Some(HoverDocFormat::Markdown), + keywords: true, + }, range, ) .unwrap() @@ -95,7 +119,11 @@ fn check_hover_range_no_results(ra_fixture: &str) { let (analysis, range) = fixture::range(ra_fixture); let hover = analysis .hover( - &HoverConfig { links_in_hover: false, documentation: Some(HoverDocFormat::Markdown) }, + &HoverConfig { + links_in_hover: false, + documentation: Some(HoverDocFormat::Markdown), + keywords: true, + }, range, ) .unwrap(); diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs index cc79ee55b7d..9e5eb909508 100644 --- a/crates/ide/src/static_index.rs +++ b/crates/ide/src/static_index.rs @@ -130,8 +130,11 @@ impl StaticIndex<'_> { syntax::NodeOrToken::Node(_) => None, syntax::NodeOrToken::Token(x) => Some(x), }); - let hover_config = - HoverConfig { links_in_hover: true, documentation: Some(HoverDocFormat::Markdown) }; + let hover_config = HoverConfig { + links_in_hover: true, + documentation: Some(HoverDocFormat::Markdown), + keywords: true, + }; let tokens = tokens.filter(|token| { matches!( token.kind(), diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 1629c1dd328..f2fae586024 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -244,6 +244,9 @@ config_data! { /// Whether to show documentation on hover. hover_documentation_enable: bool = "true", + /// Whether to show keyword hover popups. Only applies when + /// `#rust-analyzer.hover.documentation.enable#` is set. + hover_documentation_keywords: bool = "true", /// Use markdown syntax for links in hover. hover_links_enable: bool = "true", @@ -1187,6 +1190,7 @@ impl Config { HoverDocFormat::PlainText } }), + keywords: self.data.hover_documentation_keywords, } } diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index b0f2f1614db..00a6e3c43c5 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -318,6 +318,12 @@ Whether to show `Run` action. Only applies when -- Whether to show documentation on hover. -- +[[rust-analyzer.hover.documentation.keywords]]rust-analyzer.hover.documentation.keywords (default: `true`):: ++ +-- +Whether to show keyword hover popups. Only applies when +`#rust-analyzer.hover.documentation.enable#` is set. +-- [[rust-analyzer.hover.links.enable]]rust-analyzer.hover.links.enable (default: `true`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index fbdc69c8013..6352e968110 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -756,6 +756,11 @@ "default": true, "type": "boolean" }, + "rust-analyzer.hover.documentation.keywords": { + "markdownDescription": "Whether to show keyword hover popups. Only applies when\n`#rust-analyzer.hover.documentation.enable#` is set.", + "default": true, + "type": "boolean" + }, "rust-analyzer.hover.links.enable": { "markdownDescription": "Use markdown syntax for links in hover.", "default": true, -- cgit 1.4.1-3-g733a5 From 6d6356b103225522166496975f98b15d9827b6c8 Mon Sep 17 00:00:00 2001 From: Aleksandr Pak Date: Tue, 16 Aug 2022 18:29:22 +0300 Subject: fixup! feat: add inline_type_alias_uses assist --- crates/ide-assists/src/handlers/inline_type_alias.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/crates/ide-assists/src/handlers/inline_type_alias.rs b/crates/ide-assists/src/handlers/inline_type_alias.rs index 6b1cf9b90dc..c4e5bc9c7cb 100644 --- a/crates/ide-assists/src/handlers/inline_type_alias.rs +++ b/crates/ide-assists/src/handlers/inline_type_alias.rs @@ -975,7 +975,7 @@ fn foo() { } #[test] - fn inline_uses_across_files_fails() { + fn inline_uses_across_files_2() { check_assist( inline_type_alias_uses, r#" @@ -990,11 +990,6 @@ fn foo() { } "#, r#" -//- /lib.rs -mod foo; -type I = i32; - -//- /foo.rs use super::I; fn foo() { let _: i32 = 0; -- cgit 1.4.1-3-g733a5 From ad7a1ed8cc9ba44c6a294317a2289a0b6fd75219 Mon Sep 17 00:00:00 2001 From: Dominik Gschwind Date: Tue, 16 Aug 2022 17:30:17 +0200 Subject: fix: Fix panics on GATs involving const generics This workaround avoids constant crashing of rust analyzer when using GATs with const generics, even when the const generics are only on the `impl` block. The workaround treats GATs as non-existing if either itself or the parent has const generics and removes relevant panicking code-paths. --- crates/hir-ty/src/lower.rs | 9 ++++++++- crates/hir-ty/src/tests/regression.rs | 21 +++++++++++++++++++++ crates/hir-ty/src/utils.rs | 18 ++++++++++-------- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 239f66bcb7e..3ec321ad371 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -509,7 +509,14 @@ impl<'a> TyLoweringContext<'a> { TyKind::Placeholder(to_placeholder_idx(self.db, param_id.into())) } ParamLoweringMode::Variable => { - let idx = generics.param_idx(param_id.into()).expect("matching generics"); + let idx = match generics.param_idx(param_id.into()) { + None => { + never!("no matching generics"); + return (TyKind::Error.intern(Interner), None); + } + Some(idx) => idx, + }; + TyKind::BoundVar(BoundVar::new(self.in_binders, idx)) } } diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs index 93a88ab58ef..9b64fccccd2 100644 --- a/crates/hir-ty/src/tests/regression.rs +++ b/crates/hir-ty/src/tests/regression.rs @@ -1526,6 +1526,27 @@ unsafe impl Storage for InlineStorage { ); } +#[test] +fn gat_crash_3() { + cov_mark::check!(ignore_gats); + check_no_mismatches( + r#" +trait Collection { + type Item; + type Member: Collection; + fn add(&mut self, value: Self::Item) -> Result<(), Self::Error>; +} +struct ConstGen { + data: [T; N], +} +impl Collection for ConstGen { + type Item = T; + type Member = ConstGen; +} + "#, + ); +} + #[test] fn cfgd_out_self_param() { cov_mark::check!(cfgd_out_self_param); diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index 83319755da7..bdb9ade9c85 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -176,10 +176,16 @@ pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics { let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def))); if parent_generics.is_some() && matches!(def, GenericDefId::TypeAliasId(_)) { let params = db.generic_params(def); + let parent_params = &parent_generics.as_ref().unwrap().params; let has_consts = params.iter().any(|(_, x)| matches!(x, TypeOrConstParamData::ConstParamData(_))); - return if has_consts { - // XXX: treat const generic associated types as not existing to avoid crashes (#11769) + let parent_has_consts = + parent_params.iter().any(|(_, x)| matches!(x, TypeOrConstParamData::ConstParamData(_))); + return if has_consts || parent_has_consts { + // XXX: treat const generic associated types as not existing to avoid crashes + // (#11769, #12193) + // Note: also crashes when the parent has const generics (also even if the GAT + // doesn't use them), see `tests::regression::gat_crash_3` for an example. // // Chalk expects the inner associated type's parameters to come // *before*, not after the trait's generics as we've always done it. @@ -264,12 +270,8 @@ impl Generics { fn find_param(&self, param: TypeOrConstParamId) -> Option<(usize, &TypeOrConstParamData)> { if param.parent == self.def { - let (idx, (_local_id, data)) = self - .params - .iter() - .enumerate() - .find(|(_, (idx, _))| *idx == param.local_id) - .unwrap(); + let (idx, (_local_id, data)) = + self.params.iter().enumerate().find(|(_, (idx, _))| *idx == param.local_id)?; let parent_len = self.parent_generics().map_or(0, Generics::len); Some((parent_len + idx, data)) } else { -- cgit 1.4.1-3-g733a5 From 9233298e71f08404838a1051a5b211255de4b79d Mon Sep 17 00:00:00 2001 From: Tim van Elsloo Date: Tue, 16 Aug 2022 17:36:25 +0200 Subject: Revert "Revert "Allow dynamic linking for iOS/tvOS targets."" This reverts commit 16e10bf81ee73f61cf813acef3d5dbbce4f66da2. # Conflicts: # compiler/rustc_target/src/spec/apple_sdk_base.rs --- compiler/rustc_target/src/spec/apple_sdk_base.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/apple_sdk_base.rs b/compiler/rustc_target/src/spec/apple_sdk_base.rs index bf3ebaa2840..49e302676a7 100644 --- a/compiler/rustc_target/src/spec/apple_sdk_base.rs +++ b/compiler/rustc_target/src/spec/apple_sdk_base.rs @@ -65,7 +65,6 @@ pub fn opts(os: &'static str, arch: Arch) -> TargetOptions { TargetOptions { abi: target_abi(arch).into(), cpu: target_cpu(arch).into(), - dynamic_linking: false, link_env_remove: link_env_remove(arch), has_thread_local: false, ..super::apple_base::opts(os, target_arch_name(arch), target_abi(arch)) -- cgit 1.4.1-3-g733a5 From 7fb7c248c7b37699da7eb5944f45a9b59121b827 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 16 Aug 2022 18:12:15 +0200 Subject: Add `.enable` suffix --- crates/rust-analyzer/src/config.rs | 6 +++--- docs/user/generated_config.adoc | 2 +- editors/code/package.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index f2fae586024..e63cfb163ca 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -243,10 +243,10 @@ config_data! { hover_actions_run_enable: bool = "true", /// Whether to show documentation on hover. - hover_documentation_enable: bool = "true", + hover_documentation_enable: bool = "true", /// Whether to show keyword hover popups. Only applies when /// `#rust-analyzer.hover.documentation.enable#` is set. - hover_documentation_keywords: bool = "true", + hover_documentation_keywords_enable: bool = "true", /// Use markdown syntax for links in hover. hover_links_enable: bool = "true", @@ -1190,7 +1190,7 @@ impl Config { HoverDocFormat::PlainText } }), - keywords: self.data.hover_documentation_keywords, + keywords: self.data.hover_documentation_keywords_enable, } } diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 00a6e3c43c5..e3dbeec1fbd 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -318,7 +318,7 @@ Whether to show `Run` action. Only applies when -- Whether to show documentation on hover. -- -[[rust-analyzer.hover.documentation.keywords]]rust-analyzer.hover.documentation.keywords (default: `true`):: +[[rust-analyzer.hover.documentation.keywords.enable]]rust-analyzer.hover.documentation.keywords.enable (default: `true`):: + -- Whether to show keyword hover popups. Only applies when diff --git a/editors/code/package.json b/editors/code/package.json index 6352e968110..0714b356fe0 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -756,7 +756,7 @@ "default": true, "type": "boolean" }, - "rust-analyzer.hover.documentation.keywords": { + "rust-analyzer.hover.documentation.keywords.enable": { "markdownDescription": "Whether to show keyword hover popups. Only applies when\n`#rust-analyzer.hover.documentation.enable#` is set.", "default": true, "type": "boolean" -- cgit 1.4.1-3-g733a5 From 1f73cbe8390d4a8ebe4e4039891567d8358c2c70 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 16 Aug 2022 19:13:10 +0200 Subject: Revert #12947, trigger workspace switches on all structure changes again --- crates/rust-analyzer/src/global_state.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index b5f6aef2e1a..c55bbbbe6ef 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs @@ -8,7 +8,7 @@ use std::{sync::Arc, time::Instant}; use crossbeam_channel::{unbounded, Receiver, Sender}; use flycheck::FlycheckHandle; use ide::{Analysis, AnalysisHost, Cancellable, Change, FileId}; -use ide_db::base_db::{CrateId, FileLoader, SourceDatabase, SourceDatabaseExt}; +use ide_db::base_db::{CrateId, FileLoader, SourceDatabase}; use lsp_types::{SemanticTokens, Url}; use parking_lot::{Mutex, RwLock}; use proc_macro_api::ProcMacroServer; @@ -176,9 +176,9 @@ impl GlobalState { pub(crate) fn process_changes(&mut self) -> bool { let _p = profile::span("GlobalState::process_changes"); - let mut fs_refresh_changes = Vec::new(); // A file was added or deleted let mut has_structure_changes = false; + let mut workspace_structure_change = None; let (change, changed_files) = { let mut change = Change::new(); @@ -192,7 +192,7 @@ impl GlobalState { if let Some(path) = vfs.file_path(file.file_id).as_path() { let path = path.to_path_buf(); if reload::should_refresh_for_change(&path, file.change_kind) { - fs_refresh_changes.push((path, file.file_id)); + workspace_structure_change = Some(path); } if file.is_created_or_deleted() { has_structure_changes = true; @@ -227,11 +227,10 @@ impl GlobalState { { let raw_database = self.analysis_host.raw_database(); - let workspace_structure_change = - fs_refresh_changes.into_iter().find(|&(_, file_id)| { - !raw_database.source_root(raw_database.file_source_root(file_id)).is_library - }); - if let Some((path, _)) = workspace_structure_change { + // FIXME: ideally we should only trigger a workspace fetch for non-library changes + // but somethings going wrong with the source root business when we add a new local + // crate see https://github.com/rust-lang/rust-analyzer/issues/13029 + if let Some(path) = workspace_structure_change { self.fetch_workspaces_queue .request_op(format!("workspace vfs file change: {}", path.display())); } -- cgit 1.4.1-3-g733a5 From a0b257c9d91d00c054376facc6681f563f1a5e1b Mon Sep 17 00:00:00 2001 From: David Barsky Date: Tue, 16 Aug 2022 13:38:50 -0400 Subject: chore: remove unused `currentExtensionIsNightly()` in config.ts --- editors/code/src/config.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 1c58040d58c..b83582a344a 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -5,8 +5,6 @@ import { log } from "./util"; export type UpdatesChannel = "stable" | "nightly"; -const NIGHTLY_TAG = "nightly"; - export type RunnableEnvCfg = | undefined | Record @@ -175,10 +173,6 @@ export class Config { gotoTypeDef: this.get("hover.actions.gotoTypeDef.enable"), }; } - - get currentExtensionIsNightly() { - return this.package.releaseTag === NIGHTLY_TAG; - } } export async function updateConfig(config: vscode.WorkspaceConfiguration) { -- cgit 1.4.1-3-g733a5 From 70dd980c8d27dbb748de0660ceed7cfdc2413914 Mon Sep 17 00:00:00 2001 From: Mohsen Zohrevandi Date: Mon, 15 Aug 2022 16:02:49 -0700 Subject: Update fortanix-sgx-abi and export some useful SGX usercall traits Update fortanix-sgx-abi to 0.5.0 to add support for cancel queue (see https://github.com/fortanix/rust-sgx/pull/405 and https://github.com/fortanix/rust-sgx/pull/404). Export some useful traits for processing SGX usercall. This is needed for https://github.com/fortanix/rust-sgx/pull/404 to avoid duplication. --- Cargo.lock | 4 ++-- library/std/Cargo.toml | 2 +- library/std/src/os/fortanix_sgx/mod.rs | 1 + library/std/src/sys/sgx/abi/usercalls/alloc.rs | 2 ++ library/std/src/sys/sgx/abi/usercalls/mod.rs | 8 +++++++- library/std/src/sys/sgx/abi/usercalls/raw.rs | 24 +++++++++++++++++++++--- 6 files changed, 34 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 395f5a127bd..cee895acf75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1421,9 +1421,9 @@ dependencies = [ [[package]] name = "fortanix-sgx-abi" -version = "0.3.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c56c422ef86062869b2d57ae87270608dc5929969dd130a6e248979cf4fb6ca6" +checksum = "57cafc2274c10fab234f176b25903ce17e690fca7597090d50880e047a0389c5" dependencies = [ "compiler_builtins", "rustc-std-workspace-core", diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 229e546e085..3da9565a86d 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -39,7 +39,7 @@ rand = "0.7" dlmalloc = { version = "0.2.3", features = ['rustc-dep-of-std'] } [target.x86_64-fortanix-unknown-sgx.dependencies] -fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] } +fortanix-sgx-abi = { version = "0.5.0", features = ['rustc-dep-of-std'] } [target.'cfg(target_os = "hermit")'.dependencies] hermit-abi = { version = "0.2.0", features = ['rustc-dep-of-std'] } diff --git a/library/std/src/os/fortanix_sgx/mod.rs b/library/std/src/os/fortanix_sgx/mod.rs index a40dabe190a..da100b689db 100644 --- a/library/std/src/os/fortanix_sgx/mod.rs +++ b/library/std/src/os/fortanix_sgx/mod.rs @@ -26,6 +26,7 @@ pub mod usercalls { free, insecure_time, launch_thread, read, read_alloc, send, wait, write, }; pub use crate::sys::abi::usercalls::raw::{do_usercall, Usercalls as UsercallNrs}; + pub use crate::sys::abi::usercalls::raw::{Register, RegisterArgument, ReturnValue}; // fortanix-sgx-abi re-exports pub use crate::sys::abi::usercalls::raw::Error; diff --git a/library/std/src/sys/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/sgx/abi/usercalls/alloc.rs index 66fa1efbf10..b5bf9c3f243 100644 --- a/library/std/src/sys/sgx/abi/usercalls/alloc.rs +++ b/library/std/src/sys/sgx/abi/usercalls/alloc.rs @@ -56,6 +56,8 @@ unsafe impl UserSafeSized for Usercall {} #[unstable(feature = "sgx_platform", issue = "56975")] unsafe impl UserSafeSized for Return {} #[unstable(feature = "sgx_platform", issue = "56975")] +unsafe impl UserSafeSized for Cancel {} +#[unstable(feature = "sgx_platform", issue = "56975")] unsafe impl UserSafeSized for [T; 2] {} /// A type that can be represented in memory as one or more `UserSafeSized`s. diff --git a/library/std/src/sys/sgx/abi/usercalls/mod.rs b/library/std/src/sys/sgx/abi/usercalls/mod.rs index 79d1db5e1c5..e19e843267a 100644 --- a/library/std/src/sys/sgx/abi/usercalls/mod.rs +++ b/library/std/src/sys/sgx/abi/usercalls/mod.rs @@ -292,12 +292,17 @@ fn check_os_error(err: Result) -> i32 { } } -trait FromSgxResult { +/// Translate the raw result of an SGX usercall. +#[unstable(feature = "sgx_platform", issue = "56975")] +pub trait FromSgxResult { + /// Return type type Return; + /// Translate the raw result of an SGX usercall. fn from_sgx_result(self) -> IoResult; } +#[unstable(feature = "sgx_platform", issue = "56975")] impl FromSgxResult for (Result, T) { type Return = T; @@ -310,6 +315,7 @@ impl FromSgxResult for (Result, T) { } } +#[unstable(feature = "sgx_platform", issue = "56975")] impl FromSgxResult for Result { type Return = (); diff --git a/library/std/src/sys/sgx/abi/usercalls/raw.rs b/library/std/src/sys/sgx/abi/usercalls/raw.rs index 4267b96ccd5..10c1456d4fd 100644 --- a/library/std/src/sys/sgx/abi/usercalls/raw.rs +++ b/library/std/src/sys/sgx/abi/usercalls/raw.rs @@ -37,14 +37,23 @@ pub unsafe fn do_usercall( (a, b) } -type Register = u64; +/// A value passed or returned in a CPU register. +#[unstable(feature = "sgx_platform", issue = "56975")] +pub type Register = u64; -trait RegisterArgument { +/// Translate a type from/to Register to be used as an argument. +#[unstable(feature = "sgx_platform", issue = "56975")] +pub trait RegisterArgument { + /// Translate a Register to Self. fn from_register(_: Register) -> Self; + /// Translate self to a Register. fn into_register(self) -> Register; } -trait ReturnValue { +/// Translate a pair of Registers to the raw usercall return value. +#[unstable(feature = "sgx_platform", issue = "56975")] +pub trait ReturnValue { + /// Translate a pair of Registers to the raw usercall return value. fn from_registers(call: &'static str, regs: (Register, Register)) -> Self; } @@ -68,6 +77,7 @@ macro_rules! define_usercalls { macro_rules! define_ra { (< $i:ident > $t:ty) => { + #[unstable(feature = "sgx_platform", issue = "56975")] impl<$i> RegisterArgument for $t { fn from_register(a: Register) -> Self { a as _ @@ -78,6 +88,7 @@ macro_rules! define_ra { } }; ($i:ty as $t:ty) => { + #[unstable(feature = "sgx_platform", issue = "56975")] impl RegisterArgument for $t { fn from_register(a: Register) -> Self { a as $i as _ @@ -88,6 +99,7 @@ macro_rules! define_ra { } }; ($t:ty) => { + #[unstable(feature = "sgx_platform", issue = "56975")] impl RegisterArgument for $t { fn from_register(a: Register) -> Self { a as _ @@ -112,6 +124,7 @@ define_ra!(usize as isize); define_ra!( *const T); define_ra!( *mut T); +#[unstable(feature = "sgx_platform", issue = "56975")] impl RegisterArgument for bool { fn from_register(a: Register) -> bool { if a != 0 { true } else { false } @@ -121,6 +134,7 @@ impl RegisterArgument for bool { } } +#[unstable(feature = "sgx_platform", issue = "56975")] impl RegisterArgument for Option> { fn from_register(a: Register) -> Option> { NonNull::new(a as _) @@ -130,12 +144,14 @@ impl RegisterArgument for Option> { } } +#[unstable(feature = "sgx_platform", issue = "56975")] impl ReturnValue for ! { fn from_registers(call: &'static str, _regs: (Register, Register)) -> Self { rtabort!("Usercall {call}: did not expect to be re-entered"); } } +#[unstable(feature = "sgx_platform", issue = "56975")] impl ReturnValue for () { fn from_registers(call: &'static str, usercall_retval: (Register, Register)) -> Self { rtassert!(usercall_retval.0 == 0); @@ -144,6 +160,7 @@ impl ReturnValue for () { } } +#[unstable(feature = "sgx_platform", issue = "56975")] impl ReturnValue for T { fn from_registers(call: &'static str, usercall_retval: (Register, Register)) -> Self { rtassert!(usercall_retval.1 == 0); @@ -151,6 +168,7 @@ impl ReturnValue for T { } } +#[unstable(feature = "sgx_platform", issue = "56975")] impl ReturnValue for (T, U) { fn from_registers(_call: &'static str, regs: (Register, Register)) -> Self { (T::from_register(regs.0), U::from_register(regs.1)) -- cgit 1.4.1-3-g733a5 From ed27a4c51601b624e410bb60328b5844fc6c5dd4 Mon Sep 17 00:00:00 2001 From: Corwin Date: Tue, 16 Aug 2022 20:10:31 +0100 Subject: add the armv4t-none-eabi target --- compiler/rustc_target/src/spec/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 0b49edc232c..cf6cb75d49a 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1028,6 +1028,7 @@ supported_targets! { ("mipsel-sony-psp", mipsel_sony_psp), ("mipsel-unknown-none", mipsel_unknown_none), ("thumbv4t-none-eabi", thumbv4t_none_eabi), + ("armv4t-none-eabi", armv4t_none_eabi), ("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu), ("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32), -- cgit 1.4.1-3-g733a5 From 2aa4aa70ddd11ebc56667dbb3907c93a5a0176c2 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 16 Aug 2022 12:48:04 -0700 Subject: rustdoc: factor Type::QPath out into its own box This reduces the size of Type. --- src/librustdoc/clean/auto_trait.rs | 12 +++++++----- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/mod.rs | 31 ++++++++++++++----------------- src/librustdoc/clean/types.rs | 27 +++++++++++++++------------ src/librustdoc/html/format.rs | 7 ++++++- src/librustdoc/html/render/mod.rs | 4 ++-- src/librustdoc/json/conversions.rs | 4 ++-- 7 files changed, 47 insertions(+), 40 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index a94520b1219..5441a7bd29e 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -551,13 +551,15 @@ where } WherePredicate::EqPredicate { lhs, rhs } => { match lhs { - Type::QPath { ref assoc, ref self_type, ref trait_, .. } => { + Type::QPath(box QPathData { + ref assoc, ref self_type, ref trait_, .. + }) => { let ty = &*self_type; let mut new_trait = trait_.clone(); if self.is_fn_trait(trait_) && assoc.name == sym::Output { ty_to_fn - .entry(*ty.clone()) + .entry(ty.clone()) .and_modify(|e| { *e = (e.0.clone(), Some(rhs.ty().unwrap().clone())) }) @@ -582,7 +584,7 @@ where // to 'T: Iterator' GenericArgs::AngleBracketed { ref mut bindings, .. } => { bindings.push(TypeBinding { - assoc: *assoc.clone(), + assoc: assoc.clone(), kind: TypeBindingKind::Equality { term: rhs }, }); } @@ -596,7 +598,7 @@ where } } - let bounds = ty_to_bounds.entry(*ty.clone()).or_default(); + let bounds = ty_to_bounds.entry(ty.clone()).or_default(); bounds.insert(GenericBound::TraitBound( PolyTrait { trait_: new_trait, generic_params: Vec::new() }, @@ -613,7 +615,7 @@ where )); // Avoid creating any new duplicate bounds later in the outer // loop - ty_to_traits.entry(*ty.clone()).or_default().insert(trait_.clone()); + ty_to_traits.entry(ty.clone()).or_default().insert(trait_.clone()); } _ => panic!("Unexpected LHS {:?} for {:?}", lhs, item_def_id), } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index e56a715e857..bd5dfa4947b 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -672,7 +672,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean: g.where_predicates.retain(|pred| match pred { clean::WherePredicate::BoundPredicate { - ty: clean::QPath { self_type: box clean::Generic(ref s), trait_, .. }, + ty: clean::QPath(box clean::QPathData { self_type: clean::Generic(ref s), trait_, .. }), bounds, .. } => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.def_id() == trait_did), diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 971617a8400..5e34134597f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -410,12 +410,12 @@ fn clean_projection<'tcx>( self_type.def_id(&cx.cache) }; let should_show_cast = compute_should_show_cast(self_def_id, &trait_, &self_type); - Type::QPath { - assoc: Box::new(projection_to_path_segment(ty, cx)), + Type::QPath(Box::new(QPathData { + assoc: projection_to_path_segment(ty, cx), should_show_cast, - self_type: Box::new(self_type), + self_type, trait_, - } + })) } fn compute_should_show_cast(self_def_id: Option, trait_: &Path, self_type: &Type) -> bool { @@ -1182,7 +1182,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( .where_predicates .drain_filter(|pred| match *pred { WherePredicate::BoundPredicate { - ty: QPath { ref assoc, ref self_type, ref trait_, .. }, + ty: QPath(box QPathData { ref assoc, ref self_type, ref trait_, .. }), .. } => { if assoc.name != my_name { @@ -1191,7 +1191,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( if trait_.def_id() != assoc_item.container_id(tcx) { return false; } - match **self_type { + match *self_type { Generic(ref s) if *s == kw::SelfUpper => {} _ => return false, } @@ -1324,15 +1324,12 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type let self_def_id = DefId::local(qself.hir_id.owner.local_def_index); let self_type = clean_ty(qself, cx); let should_show_cast = compute_should_show_cast(Some(self_def_id), &trait_, &self_type); - Type::QPath { - assoc: Box::new(clean_path_segment( - p.segments.last().expect("segments were empty"), - cx, - )), + Type::QPath(Box::new(QPathData { + assoc: clean_path_segment(p.segments.last().expect("segments were empty"), cx), should_show_cast, - self_type: Box::new(self_type), + self_type, trait_, - } + })) } hir::QPath::TypeRelative(qself, segment) => { let ty = hir_ty_to_ty(cx.tcx, hir_ty); @@ -1347,12 +1344,12 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type let self_def_id = res.opt_def_id(); let self_type = clean_ty(qself, cx); let should_show_cast = compute_should_show_cast(self_def_id, &trait_, &self_type); - Type::QPath { - assoc: Box::new(clean_path_segment(segment, cx)), + Type::QPath(Box::new(QPathData { + assoc: clean_path_segment(segment, cx), should_show_cast, - self_type: Box::new(self_type), + self_type, trait_, - } + })) } hir::QPath::LangItem(..) => bug!("clean: requiring documentation of lang item"), } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 1a4786c9b06..7bbd2b19f2e 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1556,13 +1556,7 @@ pub(crate) enum Type { BorrowedRef { lifetime: Option, mutability: Mutability, type_: Box }, /// A qualified path to an associated item: `::Name` - QPath { - assoc: Box, - self_type: Box, - /// FIXME: compute this field on demand. - should_show_cast: bool, - trait_: Path, - }, + QPath(Box), /// A type that is inferred: `_` Infer, @@ -1660,8 +1654,8 @@ impl Type { } pub(crate) fn projection(&self) -> Option<(&Type, DefId, PathSegment)> { - if let QPath { self_type, trait_, assoc, .. } = self { - Some((self_type, trait_.def_id(), *assoc.clone())) + if let QPath(box QPathData { self_type, trait_, assoc, .. }) = self { + Some((self_type, trait_.def_id(), assoc.clone())) } else { None } @@ -1685,7 +1679,7 @@ impl Type { Slice(..) => PrimitiveType::Slice, Array(..) => PrimitiveType::Array, RawPointer(..) => PrimitiveType::RawPointer, - QPath { ref self_type, .. } => return self_type.inner_def_id(cache), + QPath(box QPathData { ref self_type, .. }) => return self_type.inner_def_id(cache), Generic(_) | Infer | ImplTrait(_) => return None, }; cache.and_then(|c| Primitive(t).def_id(c)) @@ -1699,6 +1693,15 @@ impl Type { } } +#[derive(Clone, PartialEq, Eq, Debug, Hash)] +pub(crate) struct QPathData { + pub assoc: PathSegment, + pub self_type: Type, + /// FIXME: compute this field on demand. + pub should_show_cast: bool, + pub trait_: Path, +} + /// A primitive (aka, builtin) type. /// /// This represents things like `i32`, `str`, etc. @@ -2490,11 +2493,11 @@ mod size_asserts { // These are in alphabetical order, which is easy to maintain. static_assert_size!(Crate, 72); // frequently moved by-value static_assert_size!(DocFragment, 32); - static_assert_size!(GenericArg, 80); + static_assert_size!(GenericArg, 64); static_assert_size!(GenericArgs, 32); static_assert_size!(GenericParamDef, 56); static_assert_size!(Item, 56); static_assert_size!(ItemKind, 112); static_assert_size!(PathSegment, 40); - static_assert_size!(Type, 72); + static_assert_size!(Type, 56); } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 3dee4d1acc8..b023792e95a 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1079,7 +1079,12 @@ fn fmt_type<'cx>( write!(f, "impl {}", print_generic_bounds(bounds, cx)) } } - clean::QPath { ref assoc, ref self_type, ref trait_, should_show_cast } => { + clean::QPath(box clean::QPathData { + ref assoc, + ref self_type, + ref trait_, + should_show_cast, + }) => { if f.alternate() { if should_show_cast { write!(f, "<{:#} as {:#}>::", self_type.print(cx), trait_.print(cx))? diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 5ed5299e09b..1ac5186f9f6 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2623,8 +2623,8 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec { clean::Type::BorrowedRef { type_, .. } => { work.push_back(*type_); } - clean::Type::QPath { self_type, trait_, .. } => { - work.push_back(*self_type); + clean::Type::QPath(box clean::QPathData { self_type, trait_, .. }) => { + work.push_back(self_type); process_path(trait_.def_id()); } _ => {} diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 1fedb0144d1..6221591ca25 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -480,10 +480,10 @@ impl FromWithTcx for Type { mutable: mutability == ast::Mutability::Mut, type_: Box::new((*type_).into_tcx(tcx)), }, - QPath { assoc, self_type, trait_, .. } => Type::QualifiedPath { + QPath(box clean::QPathData { assoc, self_type, trait_, .. }) => Type::QualifiedPath { name: assoc.name.to_string(), args: Box::new(assoc.args.clone().into_tcx(tcx)), - self_type: Box::new((*self_type).into_tcx(tcx)), + self_type: Box::new(self_type.into_tcx(tcx)), trait_: trait_.into_tcx(tcx), }, } -- cgit 1.4.1-3-g733a5 From 238bcc940fecd89f69a305b271d06bcd9bc2ed2f Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 16 Aug 2022 13:08:54 -0700 Subject: rustdoc: box ItemKind::Trait This reduces the memory consumption of ItemKind. --- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/mod.rs | 4 ++-- src/librustdoc/clean/types.rs | 4 ++-- src/librustdoc/formats/cache.rs | 2 +- src/librustdoc/json/conversions.rs | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index bd5dfa4947b..a7048e788b6 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -62,7 +62,7 @@ pub(crate) fn try_inline( Res::Def(DefKind::Trait, did) => { record_extern_fqn(cx, did, ItemType::Trait); build_impls(cx, Some(parent_module), did, attrs, &mut ret); - clean::TraitItem(build_external_trait(cx, did)) + clean::TraitItem(Box::new(build_external_trait(cx, did))) } Res::Def(DefKind::Fn, did) => { record_extern_fqn(cx, did, ItemType::Function); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 5e34134597f..5507ffb871b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1951,12 +1951,12 @@ fn clean_maybe_renamed_item<'tcx>( .map(|ti| clean_trait_item(cx.tcx.hir().trait_item(ti.id), cx)) .collect(); - TraitItem(Trait { + TraitItem(Box::new(Trait { def_id, items, generics: clean_generics(generics, cx), bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(), - }) + })) } ItemKind::ExternCrate(orig_name) => { return clean_extern_crate(item, name, orig_name, cx); diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 7bbd2b19f2e..61cfd7ea40d 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -727,7 +727,7 @@ pub(crate) enum ItemKind { OpaqueTyItem(OpaqueTy), StaticItem(Static), ConstantItem(Constant), - TraitItem(Trait), + TraitItem(Box), TraitAliasItem(TraitAlias), ImplItem(Box), /// A required method in a trait declaration meaning it's only a function signature. @@ -2497,7 +2497,7 @@ mod size_asserts { static_assert_size!(GenericArgs, 32); static_assert_size!(GenericParamDef, 56); static_assert_size!(Item, 56); - static_assert_size!(ItemKind, 112); + static_assert_size!(ItemKind, 96); static_assert_size!(PathSegment, 40); static_assert_size!(Type, 56); } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 2b2691e53bb..86392610d2c 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -227,7 +227,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { if let clean::TraitItem(ref t) = *item.kind { self.cache.traits.entry(item.item_id.expect_def_id()).or_insert_with(|| { clean::TraitWithExtraInfo { - trait_: t.clone(), + trait_: *t.clone(), is_notable: item.attrs.has_doc_flag(sym::notable_trait), } }); diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 6221591ca25..c4e8b6f5f84 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -248,7 +248,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { VariantItem(v) => ItemEnum::Variant(v.into_tcx(tcx)), FunctionItem(f) => ItemEnum::Function(from_function(f, header.unwrap(), tcx)), ForeignFunctionItem(f) => ItemEnum::Function(from_function(f, header.unwrap(), tcx)), - TraitItem(t) => ItemEnum::Trait(t.into_tcx(tcx)), + TraitItem(t) => ItemEnum::Trait((*t).into_tcx(tcx)), TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_tcx(tcx)), MethodItem(m, _) => ItemEnum::Method(from_function_method(m, true, header.unwrap(), tcx)), TyMethodItem(m) => ItemEnum::Method(from_function_method(m, false, header.unwrap(), tcx)), -- cgit 1.4.1-3-g733a5 From 39d17efde7d2da436f349c1b0ca55c37bae0254f Mon Sep 17 00:00:00 2001 From: Dorian Scheidt Date: Sat, 13 Aug 2022 13:29:41 -0500 Subject: feat: Generate static method using Self::assoc() syntax This change improves the `generate_function` assist to support generating static methods/associated functions using the `Self::assoc()` syntax. Previously, one could generate a static method, but only when specifying the type name directly (like `Foo::assoc()`). After this change, `Self` is supported as well as the type name. Fixes #13012 --- .../ide-assists/src/handlers/generate_function.rs | 64 ++++++++++++++++++---- 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/crates/ide-assists/src/handlers/generate_function.rs b/crates/ide-assists/src/handlers/generate_function.rs index d564a054089..49345cb983f 100644 --- a/crates/ide-assists/src/handlers/generate_function.rs +++ b/crates/ide-assists/src/handlers/generate_function.rs @@ -61,7 +61,7 @@ fn gen_fn(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { } let fn_name = &*name_ref.text(); - let target_module; + let mut target_module = None; let mut adt_name = None; let (target, file, insert_offset) = match path.qualifier() { @@ -78,16 +78,11 @@ fn gen_fn(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { } } - let current_module = ctx.sema.scope(call.syntax())?.module(); - let module = adt.module(ctx.sema.db); - target_module = if current_module == module { None } else { Some(module) }; - if current_module.krate() != module.krate() { - return None; - } - let (impl_, file) = get_adt_source(ctx, &adt, fn_name)?; - let (target, insert_offset) = get_method_target(ctx, &module, &impl_)?; - adt_name = if impl_.is_none() { Some(adt.name(ctx.sema.db)) } else { None }; - (target, file, insert_offset) + static_method_target(ctx, &call, adt, &mut target_module, fn_name, &mut adt_name)? + } + Some(hir::PathResolution::SelfType(impl_)) => { + let adt = impl_.self_ty(ctx.db()).as_adt()?; + static_method_target(ctx, &call, adt, &mut target_module, fn_name, &mut adt_name)? } _ => { return None; @@ -399,6 +394,26 @@ fn get_method_target( Some((target.clone(), get_insert_offset(&target))) } +fn static_method_target( + ctx: &AssistContext<'_>, + call: &CallExpr, + adt: hir::Adt, + target_module: &mut Option, + fn_name: &str, + adt_name: &mut Option, +) -> Option<(GeneratedFunctionTarget, FileId, TextSize)> { + let current_module = ctx.sema.scope(call.syntax())?.module(); + let module = adt.module(ctx.sema.db); + *target_module = if current_module == module { None } else { Some(module) }; + if current_module.krate() != module.krate() { + return None; + } + let (impl_, file) = get_adt_source(ctx, &adt, fn_name)?; + let (target, insert_offset) = get_method_target(ctx, &module, &impl_)?; + *adt_name = if impl_.is_none() { Some(adt.name(ctx.sema.db)) } else { None }; + Some((target, file, insert_offset)) +} + fn get_insert_offset(target: &GeneratedFunctionTarget) -> TextSize { match &target { GeneratedFunctionTarget::BehindItem(it) => it.text_range().end(), @@ -1633,6 +1648,33 @@ fn bar() ${0:-> _} { ) } + #[test] + fn create_static_method_within_an_impl_with_self_syntax() { + check_assist( + generate_function, + r" +struct S; +impl S { + fn foo(&self) { + Self::bar$0(); + } +} +", + r" +struct S; +impl S { + fn foo(&self) { + Self::bar(); + } + + fn bar() ${0:-> _} { + todo!() + } +} +", + ) + } + #[test] fn no_panic_on_invalid_global_path() { check_assist( -- cgit 1.4.1-3-g733a5 From 23abd599e73993f1ab4599f189650141a1cd313e Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Tue, 16 Aug 2022 21:18:41 +0000 Subject: bootstrap: don't apply `-Ztls-model=initial-exec` to proc macros --- src/bootstrap/bin/rustc.rs | 15 ++++++++++++--- src/bootstrap/builder.rs | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 40a3cc6d12c..bd5790d2ea8 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -25,10 +25,11 @@ use std::time::Instant; fn main() { let args = env::args_os().skip(1).collect::>(); + let arg = |name| args.windows(2).find(|args| args[0] == name).and_then(|args| args[1].to_str()); // Detect whether or not we're a build script depending on whether --target // is passed (a bit janky...) - let target = args.windows(2).find(|w| &*w[0] == "--target").and_then(|w| w[1].to_str()); + let target = arg("--target"); let version = args.iter().find(|w| &**w == "-vV"); let verbose = match env::var("RUSTC_VERBOSE") { @@ -59,8 +60,7 @@ fn main() { cmd.args(&args).env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); // Get the name of the crate we're compiling, if any. - let crate_name = - args.windows(2).find(|args| args[0] == "--crate-name").and_then(|args| args[1].to_str()); + let crate_name = arg("--crate-name"); if let Some(crate_name) = crate_name { if let Some(target) = env::var_os("RUSTC_TIME") { @@ -106,6 +106,15 @@ fn main() { { cmd.arg("-C").arg("panic=abort"); } + + // `-Ztls-model=initial-exec` must not be applied to proc-macros, see + // issue https://github.com/rust-lang/rust/issues/100530 + if env::var("RUSTC_TLS_MODEL_INITIAL_EXEC").is_ok() + && arg("--crate-type") != Some("proc-macro") + && !matches!(crate_name, Some("proc_macro2" | "quote" | "syn" | "synstructure")) + { + cmd.arg("-Ztls-model=initial-exec"); + } } else { // FIXME(rust-lang/cargo#5754) we shouldn't be using special env vars // here, but rather Cargo should know what flags to pass rustc itself. diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 0ab4824ac0a..945299d2dcd 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1850,7 +1850,7 @@ impl<'a> Builder<'a> { // so we can't use it by default in general, but we can use it for tools // and our own internal libraries. if !mode.must_support_dlopen() && !target.triple.starts_with("powerpc-") { - rustflags.arg("-Ztls-model=initial-exec"); + cargo.env("RUSTC_TLS_MODEL_INITIAL_EXEC", "1"); } if self.config.incremental { -- cgit 1.4.1-3-g733a5 From cebf95718c32b1024a6845992bee96c50f830f3a Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Tue, 16 Aug 2022 17:53:10 -0400 Subject: Find IntoFuture::IntoFuture's poll method --- crates/hir/src/lib.rs | 5 ++-- crates/hir/src/source_analyzer.rs | 34 ++++++++++++++++++++++------ crates/ide-completion/src/completions/dot.rs | 2 +- crates/ide/src/goto_definition.rs | 34 ++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 10 deletions(-) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 7f16634afe1..46d24b9f146 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -2777,9 +2777,10 @@ impl Type { self.ty.is_unknown() } - /// Checks that particular type `ty` implements `std::future::Future`. + /// Checks that particular type `ty` implements `std::future::IntoFuture` or + /// `std::future::Future`. /// This function is used in `.await` syntax completion. - pub fn impls_future(&self, db: &dyn HirDatabase) -> bool { + pub fn impls_into_future(&self, db: &dyn HirDatabase) -> bool { let trait_ = db .lang_item(self.env.krate, SmolStr::new_inline("into_future")) .and_then(|it| { diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 756772cf84e..9418afa91da 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -27,6 +27,7 @@ use hir_def::{ use hir_expand::{ builtin_fn_macro::BuiltinFnLikeExpander, hygiene::Hygiene, + mod_path::path, name, name::{AsName, Name}, HirFileId, InFile, @@ -269,16 +270,35 @@ impl SourceAnalyzer { db: &dyn HirDatabase, await_expr: &ast::AwaitExpr, ) -> Option { - // FIXME This should be pointing to the poll of IntoFuture::Output's Future impl, but I - // don't know how to resolve the Output type so that we can query for its poll method. - let ty = self.ty_of_expr(db, &await_expr.expr()?.into())?; + let mut ty = self.ty_of_expr(db, &await_expr.expr()?.into())?.clone(); + + let into_future_trait = self + .resolver + .resolve_known_trait(db.upcast(), &path![core::future::IntoFuture]) + .map(Trait::from); + + if let Some(into_future_trait) = into_future_trait { + let type_ = Type::new_with_resolver(db, &self.resolver, ty.clone()); + if type_.impls_trait(db, into_future_trait, &[]) { + let items = into_future_trait.items(db); + let into_future_type = items.into_iter().find_map(|item| match item { + AssocItem::TypeAlias(alias) + if alias.name(db) == hir_expand::name![IntoFuture] => + { + Some(alias) + } + _ => None, + })?; + let future_trait = type_.normalize_trait_assoc_type(db, &[], into_future_type)?; + ty = future_trait.ty; + } + } - let op_fn = db + let poll_fn = db .lang_item(self.resolver.krate(), hir_expand::name![poll].to_smol_str())? .as_function()?; - let substs = hir_ty::TyBuilder::subst_for_def(db, op_fn).push(ty.clone()).build(); - - Some(self.resolve_impl_method_or_trait_def(db, op_fn, &substs)) + let substs = hir_ty::TyBuilder::subst_for_def(db, poll_fn).push(ty.clone()).build(); + Some(self.resolve_impl_method_or_trait_def(db, poll_fn, &substs)) } pub(crate) fn resolve_prefix_expr( diff --git a/crates/ide-completion/src/completions/dot.rs b/crates/ide-completion/src/completions/dot.rs index cf40ca489c0..02004ff7b68 100644 --- a/crates/ide-completion/src/completions/dot.rs +++ b/crates/ide-completion/src/completions/dot.rs @@ -19,7 +19,7 @@ pub(crate) fn complete_dot( }; // Suggest .await syntax for types that implement Future trait - if receiver_ty.impls_future(ctx.db) { + if receiver_ty.impls_into_future(ctx.db) { let mut item = CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), "await"); item.detail("expr.await"); diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index b2123b9a879..c7a922e6cc6 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs @@ -1664,6 +1664,40 @@ fn f() { ); } + #[test] + fn goto_await_into_future_poll() { + check( + r#" +//- minicore: future + +struct Futurable; + +impl core::future::IntoFuture for Futurable { + type IntoFuture = MyFut; +} + +struct MyFut; + +impl core::future::Future for MyFut { + type Output = (); + + fn poll( + //^^^^ + self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_> + ) -> std::task::Poll + { + () + } +} + +fn f() { + Futurable.await$0; +} +"#, + ); + } + #[test] fn goto_try_op() { check( -- cgit 1.4.1-3-g733a5 From eafd0dfd05cca581d66d83aab9549612ba2ed543 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 12 Aug 2022 12:20:10 +1000 Subject: Box the `MacCall` in various types. --- compiler/rustc_ast/src/ast.rs | 22 ++--- compiler/rustc_builtin_macros/src/assert.rs | 4 +- .../rustc_builtin_macros/src/assert/context.rs | 4 +- compiler/rustc_builtin_macros/src/edition_panic.rs | 4 +- compiler/rustc_expand/src/expand.rs | 24 ++--- compiler/rustc_expand/src/placeholders.rs | 6 +- compiler/rustc_parse/src/parser/expr.rs | 4 +- compiler/rustc_parse/src/parser/item.rs | 2 +- compiler/rustc_parse/src/parser/pat.rs | 2 +- compiler/rustc_parse/src/parser/stmt.rs | 2 +- compiler/rustc_parse/src/parser/ty.rs | 4 +- src/test/ui/stats/hir-stats.stderr | 110 ++++++++++----------- 12 files changed, 94 insertions(+), 94 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 3d8eee6f597..16b2a0ea672 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -770,7 +770,7 @@ pub enum PatKind { Paren(P), /// A macro pattern; pre-expansion. - MacCall(MacCall), + MacCall(P), } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] @@ -980,7 +980,7 @@ pub enum StmtKind { #[derive(Clone, Encodable, Decodable, Debug)] pub struct MacCallStmt { - pub mac: MacCall, + pub mac: P, pub style: MacStmtStyle, pub attrs: AttrVec, pub tokens: Option, @@ -1437,7 +1437,7 @@ pub enum ExprKind { InlineAsm(P), /// A macro invocation; pre-expansion. - MacCall(MacCall), + MacCall(P), /// A struct literal expression. /// @@ -2040,7 +2040,7 @@ pub enum TyKind { /// Inferred type of a `self` or `&self` argument in a method. ImplicitSelf, /// A macro in the type position. - MacCall(MacCall), + MacCall(P), /// Placeholder for a kind that has failed to be defined. Err, /// Placeholder for a `va_list`. @@ -2877,7 +2877,7 @@ pub enum ItemKind { /// A macro invocation. /// /// E.g., `foo!(..)`. - MacCall(MacCall), + MacCall(P), /// A macro definition. MacroDef(MacroDef), @@ -2951,7 +2951,7 @@ pub enum AssocItemKind { /// An associated type. TyAlias(Box), /// A macro expanding to associated items. - MacCall(MacCall), + MacCall(P), } impl AssocItemKind { @@ -3000,7 +3000,7 @@ pub enum ForeignItemKind { /// An foreign type. TyAlias(Box), /// A macro expanding to foreign items. - MacCall(MacCall), + MacCall(P), } impl From for ItemKind { @@ -3036,15 +3036,15 @@ mod size_asserts { use super::*; use rustc_data_structures::static_assert_size; // These are in alphabetical order, which is easy to maintain. - static_assert_size!(AssocItem, 160); - static_assert_size!(AssocItemKind, 72); + static_assert_size!(AssocItem, 120); + static_assert_size!(AssocItemKind, 32); static_assert_size!(Attribute, 32); static_assert_size!(Block, 48); static_assert_size!(Expr, 104); static_assert_size!(ExprKind, 72); static_assert_size!(Fn, 192); - static_assert_size!(ForeignItem, 160); - static_assert_size!(ForeignItemKind, 72); + static_assert_size!(ForeignItem, 112); + static_assert_size!(ForeignItemKind, 24); static_assert_size!(GenericBound, 88); static_assert_size!(Generics, 72); static_assert_size!(Impl, 200); diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs index 925c36edb51..119724b5049 100644 --- a/compiler/rustc_builtin_macros/src/assert.rs +++ b/compiler/rustc_builtin_macros/src/assert.rs @@ -52,7 +52,7 @@ pub fn expand_assert<'cx>( let expr = if let Some(tokens) = custom_message { let then = cx.expr( call_site_span, - ExprKind::MacCall(MacCall { + ExprKind::MacCall(P(MacCall { path: panic_path(), args: P(MacArgs::Delimited( DelimSpan::from_single(call_site_span), @@ -60,7 +60,7 @@ pub fn expand_assert<'cx>( tokens, )), prior_type_ascription: None, - }), + })), ); expr_if_not(cx, call_site_span, cond_expr, then, None) } diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index c04d04020cc..d30fd479015 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -177,7 +177,7 @@ impl<'cx, 'a> Context<'cx, 'a> { }); self.cx.expr( self.span, - ExprKind::MacCall(MacCall { + ExprKind::MacCall(P(MacCall { path: panic_path, args: P(MacArgs::Delimited( DelimSpan::from_single(self.span), @@ -185,7 +185,7 @@ impl<'cx, 'a> Context<'cx, 'a> { initial.into_iter().chain(captures).collect::(), )), prior_type_ascription: None, - }), + })), ) } diff --git a/compiler/rustc_builtin_macros/src/edition_panic.rs b/compiler/rustc_builtin_macros/src/edition_panic.rs index ea0e768a58f..3f1a8b3bc2c 100644 --- a/compiler/rustc_builtin_macros/src/edition_panic.rs +++ b/compiler/rustc_builtin_macros/src/edition_panic.rs @@ -48,7 +48,7 @@ fn expand<'cx>( MacEager::expr( cx.expr( sp, - ExprKind::MacCall(MacCall { + ExprKind::MacCall(P(MacCall { path: Path { span: sp, segments: cx @@ -64,7 +64,7 @@ fn expand<'cx>( tts, )), prior_type_ascription: None, - }), + })), ), ) } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 93eeca5b289..cc72dab84af 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -306,7 +306,7 @@ pub struct Invocation { pub enum InvocationKind { Bang { - mac: ast::MacCall, + mac: P, span: Span, }, Attr { @@ -1017,7 +1017,7 @@ trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized { fn is_mac_call(&self) -> bool { false } - fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P, Self::AttrsTy, AddSemicolon) { unreachable!() } fn pre_flat_map_node_collect_attr(_cfg: &StripUnconfigured<'_>, _attr: &ast::Attribute) {} @@ -1046,7 +1046,7 @@ impl InvocationCollectorNode for P { fn is_mac_call(&self) -> bool { matches!(self.kind, ItemKind::MacCall(..)) } - fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P, Self::AttrsTy, AddSemicolon) { let node = self.into_inner(); match node.kind { ItemKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No), @@ -1154,7 +1154,7 @@ impl InvocationCollectorNode for AstNodeWrapper, TraitItemTag> fn is_mac_call(&self) -> bool { matches!(self.wrapped.kind, AssocItemKind::MacCall(..)) } - fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P, Self::AttrsTy, AddSemicolon) { let item = self.wrapped.into_inner(); match item.kind { AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No), @@ -1179,7 +1179,7 @@ impl InvocationCollectorNode for AstNodeWrapper, ImplItemTag> fn is_mac_call(&self) -> bool { matches!(self.wrapped.kind, AssocItemKind::MacCall(..)) } - fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P, Self::AttrsTy, AddSemicolon) { let item = self.wrapped.into_inner(); match item.kind { AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No), @@ -1202,7 +1202,7 @@ impl InvocationCollectorNode for P { fn is_mac_call(&self) -> bool { matches!(self.kind, ForeignItemKind::MacCall(..)) } - fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P, Self::AttrsTy, AddSemicolon) { let node = self.into_inner(); match node.kind { ForeignItemKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No), @@ -1323,7 +1323,7 @@ impl InvocationCollectorNode for ast::Stmt { StmtKind::Local(..) | StmtKind::Empty => false, } } - fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P, Self::AttrsTy, AddSemicolon) { // We pull macro invocations (both attributes and fn-like macro calls) out of their // `StmtKind`s and treat them as statement macro invocations, not as items or expressions. let (add_semicolon, mac, attrs) = match self.kind { @@ -1387,7 +1387,7 @@ impl InvocationCollectorNode for P { fn is_mac_call(&self) -> bool { matches!(self.kind, ast::TyKind::MacCall(..)) } - fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P, Self::AttrsTy, AddSemicolon) { let node = self.into_inner(); match node.kind { TyKind::MacCall(mac) => (mac, Vec::new(), AddSemicolon::No), @@ -1411,7 +1411,7 @@ impl InvocationCollectorNode for P { fn is_mac_call(&self) -> bool { matches!(self.kind, PatKind::MacCall(..)) } - fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P, Self::AttrsTy, AddSemicolon) { let node = self.into_inner(); match node.kind { PatKind::MacCall(mac) => (mac, Vec::new(), AddSemicolon::No), @@ -1439,7 +1439,7 @@ impl InvocationCollectorNode for P { fn is_mac_call(&self) -> bool { matches!(self.kind, ExprKind::MacCall(..)) } - fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P, Self::AttrsTy, AddSemicolon) { let node = self.into_inner(); match node.kind { ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No), @@ -1466,7 +1466,7 @@ impl InvocationCollectorNode for AstNodeWrapper, OptExprTag> { fn is_mac_call(&self) -> bool { matches!(self.wrapped.kind, ast::ExprKind::MacCall(..)) } - fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) { + fn take_mac_call(self) -> (P, Self::AttrsTy, AddSemicolon) { let node = self.wrapped.into_inner(); match node.kind { ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No), @@ -1512,7 +1512,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { placeholder(fragment_kind, NodeId::placeholder_from_expn_id(expn_id), vis) } - fn collect_bang(&mut self, mac: ast::MacCall, kind: AstFragmentKind) -> AstFragment { + fn collect_bang(&mut self, mac: P, kind: AstFragmentKind) -> AstFragment { // cache the macro call span so that it can be // easily adjusted for incremental compilation let span = mac.span(); diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 0d5d6ee0794..48918541e72 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -15,12 +15,12 @@ pub fn placeholder( id: ast::NodeId, vis: Option, ) -> AstFragment { - fn mac_placeholder() -> ast::MacCall { - ast::MacCall { + fn mac_placeholder() -> P { + P(ast::MacCall { path: ast::Path { span: DUMMY_SP, segments: Vec::new(), tokens: None }, args: P(ast::MacArgs::Empty), prior_type_ascription: None, - } + }) } let ident = Ident::empty(); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 9d6d632c2e8..f7a9e3d163e 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1492,11 +1492,11 @@ impl<'a> Parser<'a> { self.struct_span_err(path.span, "macros cannot use qualified paths").emit(); } let lo = path.span; - let mac = MacCall { + let mac = P(MacCall { path, args: self.parse_mac_args()?, prior_type_ascription: self.last_type_ascription, - }; + }); (lo.to(self.prev_token.span), ExprKind::MacCall(mac)) } else if self.check(&token::OpenDelim(Delimiter::Brace)) && let Some(expr) = self.maybe_parse_struct_expr(qself.as_ref(), &path) { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index f3f070e6eb0..cd3c982ce81 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -287,7 +287,7 @@ impl<'a> Parser<'a> { return Ok(None); } else if macros_allowed && self.check_path() { // MACRO INVOCATION ITEM - (Ident::empty(), ItemKind::MacCall(self.parse_item_macro(vis)?)) + (Ident::empty(), ItemKind::MacCall(P(self.parse_item_macro(vis)?))) } else { return Ok(None); }; diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 98c974420eb..42bf8898447 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -665,7 +665,7 @@ impl<'a> Parser<'a> { fn parse_pat_mac_invoc(&mut self, path: Path) -> PResult<'a, PatKind> { self.bump(); let args = self.parse_mac_args()?; - let mac = MacCall { path, args, prior_type_ascription: self.last_type_ascription }; + let mac = P(MacCall { path, args, prior_type_ascription: self.last_type_ascription }); Ok(PatKind::MacCall(mac)) } diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index ade0f4fbc86..d2e0b557f8c 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -181,7 +181,7 @@ impl<'a> Parser<'a> { None => unreachable!(), }; - let mac = MacCall { path, args, prior_type_ascription: self.last_type_ascription }; + let mac = P(MacCall { path, args, prior_type_ascription: self.last_type_ascription }); let kind = if (style == MacStmtStyle::Braces && self.token != token::Dot diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 31b40a83e60..76b710095d7 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -598,11 +598,11 @@ impl<'a> Parser<'a> { let path = self.parse_path_inner(PathStyle::Type, ty_generics)?; if self.eat(&token::Not) { // Macro invocation in type position - Ok(TyKind::MacCall(MacCall { + Ok(TyKind::MacCall(P(MacCall { path, args: self.parse_mac_args()?, prior_type_ascription: self.last_type_ascription, - })) + }))) } else if allow_plus == AllowPlus::Yes && self.check_plus() { // `Trait1 + Trait2 + 'a` self.parse_remaining_bounds_path(Vec::new(), path, lo, true) diff --git a/src/test/ui/stats/hir-stats.stderr b/src/test/ui/stats/hir-stats.stderr index 9ea32e8d64e..61cb7b25e49 100644 --- a/src/test/ui/stats/hir-stats.stderr +++ b/src/test/ui/stats/hir-stats.stderr @@ -3,7 +3,7 @@ PRE EXPANSION AST STATS Name Accumulated Size Count Item Size ---------------------------------------------------------------- -ExprField 48 ( 0.5%) 1 48 +ExprField 48 ( 0.6%) 1 48 Attribute 64 ( 0.7%) 2 32 - Normal 32 ( 0.4%) 1 - DocComment 32 ( 0.4%) 1 @@ -14,48 +14,48 @@ WherePredicate 72 ( 0.8%) 1 72 - BoundPredicate 72 ( 0.8%) 1 Crate 72 ( 0.8%) 1 72 Arm 96 ( 1.1%) 2 48 +ForeignItem 112 ( 1.3%) 1 112 +- Fn 112 ( 1.3%) 1 FieldDef 160 ( 1.8%) 2 80 -ForeignItem 160 ( 1.8%) 1 160 -- Fn 160 ( 1.8%) 1 Stmt 160 ( 1.8%) 5 32 - Local 32 ( 0.4%) 1 - MacCall 32 ( 0.4%) 1 - Expr 96 ( 1.1%) 3 Param 160 ( 1.8%) 4 40 -FnDecl 200 ( 2.2%) 5 40 -Variant 240 ( 2.7%) 2 120 -Block 288 ( 3.2%) 6 48 +FnDecl 200 ( 2.3%) 5 40 +Variant 240 ( 2.8%) 2 120 +Block 288 ( 3.3%) 6 48 GenericBound 352 ( 4.0%) 4 88 - Trait 352 ( 4.0%) 4 -GenericParam 520 ( 5.8%) 5 104 -AssocItem 640 ( 7.2%) 4 160 -- TyAlias 320 ( 3.6%) 2 -- Fn 320 ( 3.6%) 2 -PathSegment 720 ( 8.1%) 30 24 -Expr 832 ( 9.3%) 8 104 +AssocItem 480 ( 5.5%) 4 120 +- TyAlias 240 ( 2.8%) 2 +- Fn 240 ( 2.8%) 2 +GenericParam 520 ( 6.0%) 5 104 +PathSegment 720 ( 8.3%) 30 24 +Expr 832 ( 9.6%) 8 104 - Path 104 ( 1.2%) 1 - Match 104 ( 1.2%) 1 - Struct 104 ( 1.2%) 1 -- Lit 208 ( 2.3%) 2 -- Block 312 ( 3.5%) 3 -Pat 840 ( 9.4%) 7 120 -- Struct 120 ( 1.3%) 1 -- Wild 120 ( 1.3%) 1 -- Ident 600 ( 6.7%) 5 -Ty 1_344 (15.1%) 14 96 +- Lit 208 ( 2.4%) 2 +- Block 312 ( 3.6%) 3 +Pat 840 ( 9.7%) 7 120 +- Struct 120 ( 1.4%) 1 +- Wild 120 ( 1.4%) 1 +- Ident 600 ( 6.9%) 5 +Ty 1_344 (15.5%) 14 96 - Rptr 96 ( 1.1%) 1 - Ptr 96 ( 1.1%) 1 - ImplicitSelf 192 ( 2.2%) 2 -- Path 960 (10.8%) 10 -Item 1_800 (20.2%) 9 200 -- Trait 200 ( 2.2%) 1 -- Enum 200 ( 2.2%) 1 -- ForeignMod 200 ( 2.2%) 1 -- Impl 200 ( 2.2%) 1 -- Fn 400 ( 4.5%) 2 -- Use 600 ( 6.7%) 3 +- Path 960 (11.0%) 10 +Item 1_800 (20.7%) 9 200 +- Trait 200 ( 2.3%) 1 +- Enum 200 ( 2.3%) 1 +- ForeignMod 200 ( 2.3%) 1 +- Impl 200 ( 2.3%) 1 +- Fn 400 ( 4.6%) 2 +- Use 600 ( 6.9%) 3 ---------------------------------------------------------------- -Total 8_904 +Total 8_696 POST EXPANSION AST STATS @@ -65,18 +65,18 @@ Name Accumulated Size Count Item Size ExprField 48 ( 0.5%) 1 48 GenericArgs 64 ( 0.7%) 1 64 - AngleBracketed 64 ( 0.7%) 1 -Local 72 ( 0.7%) 1 72 -WherePredicate 72 ( 0.7%) 1 72 -- BoundPredicate 72 ( 0.7%) 1 -Crate 72 ( 0.7%) 1 72 +Local 72 ( 0.8%) 1 72 +WherePredicate 72 ( 0.8%) 1 72 +- BoundPredicate 72 ( 0.8%) 1 +Crate 72 ( 0.8%) 1 72 Arm 96 ( 1.0%) 2 48 -InlineAsm 120 ( 1.2%) 1 120 -Attribute 128 ( 1.3%) 4 32 +ForeignItem 112 ( 1.2%) 1 112 +- Fn 112 ( 1.2%) 1 +InlineAsm 120 ( 1.3%) 1 120 +Attribute 128 ( 1.4%) 4 32 - DocComment 32 ( 0.3%) 1 - Normal 96 ( 1.0%) 3 FieldDef 160 ( 1.7%) 2 80 -ForeignItem 160 ( 1.7%) 1 160 -- Fn 160 ( 1.7%) 1 Stmt 160 ( 1.7%) 5 32 - Local 32 ( 0.3%) 1 - Semi 32 ( 0.3%) 1 @@ -85,39 +85,39 @@ Param 160 ( 1.7%) 4 40 FnDecl 200 ( 2.1%) 5 40 Variant 240 ( 2.5%) 2 120 Block 288 ( 3.0%) 6 48 -GenericBound 352 ( 3.6%) 4 88 -- Trait 352 ( 3.6%) 4 -GenericParam 520 ( 5.4%) 5 104 -AssocItem 640 ( 6.6%) 4 160 -- TyAlias 320 ( 3.3%) 2 -- Fn 320 ( 3.3%) 2 -PathSegment 792 ( 8.2%) 33 24 -Pat 840 ( 8.7%) 7 120 -- Struct 120 ( 1.2%) 1 -- Wild 120 ( 1.2%) 1 -- Ident 600 ( 6.2%) 5 -Expr 936 ( 9.7%) 9 104 +GenericBound 352 ( 3.7%) 4 88 +- Trait 352 ( 3.7%) 4 +AssocItem 480 ( 5.1%) 4 120 +- TyAlias 240 ( 2.5%) 2 +- Fn 240 ( 2.5%) 2 +GenericParam 520 ( 5.5%) 5 104 +PathSegment 792 ( 8.4%) 33 24 +Pat 840 ( 8.9%) 7 120 +- Struct 120 ( 1.3%) 1 +- Wild 120 ( 1.3%) 1 +- Ident 600 ( 6.3%) 5 +Expr 936 ( 9.9%) 9 104 - Path 104 ( 1.1%) 1 - Match 104 ( 1.1%) 1 - Struct 104 ( 1.1%) 1 - InlineAsm 104 ( 1.1%) 1 - Lit 208 ( 2.2%) 2 -- Block 312 ( 3.2%) 3 -Ty 1_344 (13.9%) 14 96 +- Block 312 ( 3.3%) 3 +Ty 1_344 (14.2%) 14 96 - Rptr 96 ( 1.0%) 1 - Ptr 96 ( 1.0%) 1 - ImplicitSelf 192 ( 2.0%) 2 -- Path 960 ( 9.9%) 10 -Item 2_200 (22.8%) 11 200 +- Path 960 (10.2%) 10 +Item 2_200 (23.3%) 11 200 - Trait 200 ( 2.1%) 1 - Enum 200 ( 2.1%) 1 - ExternCrate 200 ( 2.1%) 1 - ForeignMod 200 ( 2.1%) 1 - Impl 200 ( 2.1%) 1 -- Fn 400 ( 4.1%) 2 -- Use 800 ( 8.3%) 4 +- Fn 400 ( 4.2%) 2 +- Use 800 ( 8.5%) 4 ---------------------------------------------------------------- -Total 9_664 +Total 9_456 HIR STATS -- cgit 1.4.1-3-g733a5 From f77a545e94abc578b22cf48eb0085dc903f9d262 Mon Sep 17 00:00:00 2001 From: Corwin Date: Tue, 16 Aug 2022 23:15:42 +0100 Subject: add target armv4t-none-eabi --- src/doc/rustc/src/platform-support.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 01489e9aafb..f0f57f93386 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -223,6 +223,7 @@ target | std | host | notes `aarch64_be-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (big-endian, ILP32 ABI) `aarch64_be-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (big-endian) [`arm64_32-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | ARM Apple WatchOS 64-bit with 32-bit pointers +`armv4t-none-eabi` | * | | ARMv4T A32 `armv4t-unknown-linux-gnueabi` | ? | | `armv5te-unknown-linux-uclibceabi` | ? | | ARMv5TE Linux with uClibc `armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD -- cgit 1.4.1-3-g733a5 From 147032a61896db76e97bfde9fa0e711fd5e62b08 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 16 Aug 2022 15:46:17 -0700 Subject: Move the cast_float_to_int fallback code to GCC Now that we require at least LLVM 13, that codegen backend is always using its intrinsic `fptosi.sat` and `fptoui.sat` conversions, so it doesn't need the manual implementation. However, the GCC backend still needs it, so we can move all of that code down there. --- Cargo.lock | 1 - compiler/rustc_codegen_gcc/src/builder.rs | 174 ++++++++++++++++++++++- compiler/rustc_codegen_gcc/src/lib.rs | 1 + compiler/rustc_codegen_llvm/src/builder.rs | 13 +- compiler/rustc_codegen_ssa/Cargo.toml | 1 - compiler/rustc_codegen_ssa/src/traits/builder.rs | 157 +------------------- 6 files changed, 177 insertions(+), 170 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 395f5a127bd..aabb04995eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3721,7 +3721,6 @@ dependencies = [ "object 0.29.0", "pathdiff", "regex", - "rustc_apfloat", "rustc_arena", "rustc_ast", "rustc_attr", diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 4d40dd0994d..6994eeb00c3 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -15,8 +15,11 @@ use gccjit::{ Type, UnaryOp, }; +use rustc_apfloat::{ieee, Float, Round, Status}; use rustc_codegen_ssa::MemFlags; -use rustc_codegen_ssa::common::{AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope}; +use rustc_codegen_ssa::common::{ + AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope, TypeKind, +}; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::{ @@ -31,6 +34,7 @@ use rustc_codegen_ssa::traits::{ StaticBuilderMethods, }; use rustc_data_structures::fx::FxHashSet; +use rustc_middle::bug; use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; use rustc_middle::ty::layout::{FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout}; use rustc_span::Span; @@ -1271,12 +1275,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { val } - fn fptoui_sat(&mut self, _val: RValue<'gcc>, _dest_ty: Type<'gcc>) -> Option> { - None + fn fptoui_sat(&mut self, val: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { + self.fptoint_sat(false, val, dest_ty) } - fn fptosi_sat(&mut self, _val: RValue<'gcc>, _dest_ty: Type<'gcc>) -> Option> { - None + fn fptosi_sat(&mut self, val: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { + self.fptoint_sat(true, val, dest_ty) } fn instrprof_increment(&mut self, _fn_name: RValue<'gcc>, _hash: RValue<'gcc>, _num_counters: RValue<'gcc>, _index: RValue<'gcc>) { @@ -1285,6 +1289,166 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { + fn fptoint_sat(&mut self, signed: bool, val: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { + let src_ty = self.cx.val_ty(val); + let (float_ty, int_ty) = if self.cx.type_kind(src_ty) == TypeKind::Vector { + assert_eq!(self.cx.vector_length(src_ty), self.cx.vector_length(dest_ty)); + (self.cx.element_type(src_ty), self.cx.element_type(dest_ty)) + } else { + (src_ty, dest_ty) + }; + + // FIXME(jistone): the following was originally the fallback SSA implementation, before LLVM 13 + // added native `fptosi.sat` and `fptoui.sat` conversions, but it was used by GCC as well. + // Now that LLVM always relies on its own, the code has been moved to GCC, but the comments are + // still LLVM-specific. This should be updated, and use better GCC specifics if possible. + + let int_width = self.cx.int_width(int_ty); + let float_width = self.cx.float_width(float_ty); + // LLVM's fpto[su]i returns undef when the input val is infinite, NaN, or does not fit into the + // destination integer type after rounding towards zero. This `undef` value can cause UB in + // safe code (see issue #10184), so we implement a saturating conversion on top of it: + // Semantically, the mathematical value of the input is rounded towards zero to the next + // mathematical integer, and then the result is clamped into the range of the destination + // integer type. Positive and negative infinity are mapped to the maximum and minimum value of + // the destination integer type. NaN is mapped to 0. + // + // Define f_min and f_max as the largest and smallest (finite) floats that are exactly equal to + // a value representable in int_ty. + // They are exactly equal to int_ty::{MIN,MAX} if float_ty has enough significand bits. + // Otherwise, int_ty::MAX must be rounded towards zero, as it is one less than a power of two. + // int_ty::MIN, however, is either zero or a negative power of two and is thus exactly + // representable. Note that this only works if float_ty's exponent range is sufficiently large. + // f16 or 256 bit integers would break this property. Right now the smallest float type is f32 + // with exponents ranging up to 127, which is barely enough for i128::MIN = -2^127. + // On the other hand, f_max works even if int_ty::MAX is greater than float_ty::MAX. Because + // we're rounding towards zero, we just get float_ty::MAX (which is always an integer). + // This already happens today with u128::MAX = 2^128 - 1 > f32::MAX. + let int_max = |signed: bool, int_width: u64| -> u128 { + let shift_amount = 128 - int_width; + if signed { i128::MAX as u128 >> shift_amount } else { u128::MAX >> shift_amount } + }; + let int_min = |signed: bool, int_width: u64| -> i128 { + if signed { i128::MIN >> (128 - int_width) } else { 0 } + }; + + let compute_clamp_bounds_single = |signed: bool, int_width: u64| -> (u128, u128) { + let rounded_min = + ieee::Single::from_i128_r(int_min(signed, int_width), Round::TowardZero); + assert_eq!(rounded_min.status, Status::OK); + let rounded_max = + ieee::Single::from_u128_r(int_max(signed, int_width), Round::TowardZero); + assert!(rounded_max.value.is_finite()); + (rounded_min.value.to_bits(), rounded_max.value.to_bits()) + }; + let compute_clamp_bounds_double = |signed: bool, int_width: u64| -> (u128, u128) { + let rounded_min = + ieee::Double::from_i128_r(int_min(signed, int_width), Round::TowardZero); + assert_eq!(rounded_min.status, Status::OK); + let rounded_max = + ieee::Double::from_u128_r(int_max(signed, int_width), Round::TowardZero); + assert!(rounded_max.value.is_finite()); + (rounded_min.value.to_bits(), rounded_max.value.to_bits()) + }; + // To implement saturation, we perform the following steps: + // + // 1. Cast val to an integer with fpto[su]i. This may result in undef. + // 2. Compare val to f_min and f_max, and use the comparison results to select: + // a) int_ty::MIN if val < f_min or val is NaN + // b) int_ty::MAX if val > f_max + // c) the result of fpto[su]i otherwise + // 3. If val is NaN, return 0.0, otherwise return the result of step 2. + // + // This avoids resulting undef because values in range [f_min, f_max] by definition fit into the + // destination type. It creates an undef temporary, but *producing* undef is not UB. Our use of + // undef does not introduce any non-determinism either. + // More importantly, the above procedure correctly implements saturating conversion. + // Proof (sketch): + // If val is NaN, 0 is returned by definition. + // Otherwise, val is finite or infinite and thus can be compared with f_min and f_max. + // This yields three cases to consider: + // (1) if val in [f_min, f_max], the result of fpto[su]i is returned, which agrees with + // saturating conversion for inputs in that range. + // (2) if val > f_max, then val is larger than int_ty::MAX. This holds even if f_max is rounded + // (i.e., if f_max < int_ty::MAX) because in those cases, nextUp(f_max) is already larger + // than int_ty::MAX. Because val is larger than int_ty::MAX, the return value of int_ty::MAX + // is correct. + // (3) if val < f_min, then val is smaller than int_ty::MIN. As shown earlier, f_min exactly equals + // int_ty::MIN and therefore the return value of int_ty::MIN is correct. + // QED. + + let float_bits_to_llval = |bx: &mut Self, bits| { + let bits_llval = match float_width { + 32 => bx.cx().const_u32(bits as u32), + 64 => bx.cx().const_u64(bits as u64), + n => bug!("unsupported float width {}", n), + }; + bx.bitcast(bits_llval, float_ty) + }; + let (f_min, f_max) = match float_width { + 32 => compute_clamp_bounds_single(signed, int_width), + 64 => compute_clamp_bounds_double(signed, int_width), + n => bug!("unsupported float width {}", n), + }; + let f_min = float_bits_to_llval(self, f_min); + let f_max = float_bits_to_llval(self, f_max); + let int_max = self.cx.const_uint_big(int_ty, int_max(signed, int_width)); + let int_min = self.cx.const_uint_big(int_ty, int_min(signed, int_width) as u128); + let zero = self.cx.const_uint(int_ty, 0); + + // If we're working with vectors, constants must be "splatted": the constant is duplicated + // into each lane of the vector. The algorithm stays the same, we are just using the + // same constant across all lanes. + let maybe_splat = |bx: &mut Self, val| { + if bx.cx().type_kind(dest_ty) == TypeKind::Vector { + bx.vector_splat(bx.vector_length(dest_ty), val) + } else { + val + } + }; + let f_min = maybe_splat(self, f_min); + let f_max = maybe_splat(self, f_max); + let int_max = maybe_splat(self, int_max); + let int_min = maybe_splat(self, int_min); + let zero = maybe_splat(self, zero); + + // Step 1 ... + let fptosui_result = if signed { self.fptosi(val, dest_ty) } else { self.fptoui(val, dest_ty) }; + let less_or_nan = self.fcmp(RealPredicate::RealULT, val, f_min); + let greater = self.fcmp(RealPredicate::RealOGT, val, f_max); + + // Step 2: We use two comparisons and two selects, with %s1 being the + // result: + // %less_or_nan = fcmp ult %val, %f_min + // %greater = fcmp olt %val, %f_max + // %s0 = select %less_or_nan, int_ty::MIN, %fptosi_result + // %s1 = select %greater, int_ty::MAX, %s0 + // Note that %less_or_nan uses an *unordered* comparison. This + // comparison is true if the operands are not comparable (i.e., if val is + // NaN). The unordered comparison ensures that s1 becomes int_ty::MIN if + // val is NaN. + // + // Performance note: Unordered comparison can be lowered to a "flipped" + // comparison and a negation, and the negation can be merged into the + // select. Therefore, it not necessarily any more expensive than an + // ordered ("normal") comparison. Whether these optimizations will be + // performed is ultimately up to the backend, but at least x86 does + // perform them. + let s0 = self.select(less_or_nan, int_min, fptosui_result); + let s1 = self.select(greater, int_max, s0); + + // Step 3: NaN replacement. + // For unsigned types, the above step already yielded int_ty::MIN == 0 if val is NaN. + // Therefore we only need to execute this step for signed integer types. + if signed { + // LLVM has no isNaN predicate, so we use (val == val) instead + let cmp = self.fcmp(RealPredicate::RealOEQ, val, val); + self.select(cmp, s1, zero) + } else { + s1 + } + } + #[cfg(feature="master")] pub fn shuffle_vector(&mut self, v1: RValue<'gcc>, v2: RValue<'gcc>, mask: RValue<'gcc>) -> RValue<'gcc> { let struct_type = mask.get_type().is_struct().expect("mask of struct type"); diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 8a206c0368f..223466fb9b5 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -19,6 +19,7 @@ #![warn(rust_2018_idioms)] #![warn(unused_lifetimes)] +extern crate rustc_apfloat; extern crate rustc_ast; extern crate rustc_codegen_ssa; extern crate rustc_data_structures; diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 073feecb164..e7e373bf45d 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -725,11 +725,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { unsafe { llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, UNNAMED) } } - fn fptoui_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> { + fn fptoui_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.fptoint_sat(false, val, dest_ty) } - fn fptosi_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> { + fn fptosi_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.fptoint_sat(true, val, dest_ty) } @@ -1429,12 +1429,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { } } - fn fptoint_sat( - &mut self, - signed: bool, - val: &'ll Value, - dest_ty: &'ll Type, - ) -> Option<&'ll Value> { + fn fptoint_sat(&mut self, signed: bool, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { let src_ty = self.cx.val_ty(val); let (float_ty, int_ty, vector_length) = if self.cx.type_kind(src_ty) == TypeKind::Vector { assert_eq!(self.cx.vector_length(src_ty), self.cx.vector_length(dest_ty)); @@ -1459,7 +1454,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { format!("llvm.{}.sat.i{}.f{}", instr, int_width, float_width) }; let f = self.declare_cfn(&name, llvm::UnnamedAddr::No, self.type_func(&[src_ty], dest_ty)); - Some(self.call(self.type_func(&[src_ty], dest_ty), f, &[val], None)) + self.call(self.type_func(&[src_ty], dest_ty), f, &[val], None) } pub(crate) fn landing_pad( diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 46d6344dbb2..d868e3d56ba 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -26,7 +26,6 @@ rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } rustc_middle = { path = "../rustc_middle" } -rustc_apfloat = { path = "../rustc_apfloat" } rustc_attr = { path = "../rustc_attr" } rustc_symbol_mangling = { path = "../rustc_symbol_mangling" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 9f49749bb41..10cf8948b5a 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -1,6 +1,5 @@ use super::abi::AbiBuilderMethods; use super::asm::AsmBuilderMethods; -use super::consts::ConstMethods; use super::coverageinfo::CoverageInfoBuilderMethods; use super::debuginfo::DebugInfoBuilderMethods; use super::intrinsic::IntrinsicCallMethods; @@ -15,7 +14,6 @@ use crate::mir::operand::OperandRef; use crate::mir::place::PlaceRef; use crate::MemFlags; -use rustc_apfloat::{ieee, Float, Round, Status}; use rustc_middle::ty::layout::{HasParamEnv, TyAndLayout}; use rustc_middle::ty::Ty; use rustc_span::Span; @@ -188,8 +186,8 @@ pub trait BuilderMethods<'a, 'tcx>: fn trunc(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn sext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; - fn fptoui_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Option; - fn fptosi_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Option; + fn fptoui_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; + fn fptosi_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn fptoui(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn fptosi(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn uitofp(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; @@ -223,156 +221,7 @@ pub trait BuilderMethods<'a, 'tcx>: return if signed { self.fptosi(x, dest_ty) } else { self.fptoui(x, dest_ty) }; } - let try_sat_result = - if signed { self.fptosi_sat(x, dest_ty) } else { self.fptoui_sat(x, dest_ty) }; - if let Some(try_sat_result) = try_sat_result { - return try_sat_result; - } - - let int_width = self.cx().int_width(int_ty); - let float_width = self.cx().float_width(float_ty); - // LLVM's fpto[su]i returns undef when the input x is infinite, NaN, or does not fit into the - // destination integer type after rounding towards zero. This `undef` value can cause UB in - // safe code (see issue #10184), so we implement a saturating conversion on top of it: - // Semantically, the mathematical value of the input is rounded towards zero to the next - // mathematical integer, and then the result is clamped into the range of the destination - // integer type. Positive and negative infinity are mapped to the maximum and minimum value of - // the destination integer type. NaN is mapped to 0. - // - // Define f_min and f_max as the largest and smallest (finite) floats that are exactly equal to - // a value representable in int_ty. - // They are exactly equal to int_ty::{MIN,MAX} if float_ty has enough significand bits. - // Otherwise, int_ty::MAX must be rounded towards zero, as it is one less than a power of two. - // int_ty::MIN, however, is either zero or a negative power of two and is thus exactly - // representable. Note that this only works if float_ty's exponent range is sufficiently large. - // f16 or 256 bit integers would break this property. Right now the smallest float type is f32 - // with exponents ranging up to 127, which is barely enough for i128::MIN = -2^127. - // On the other hand, f_max works even if int_ty::MAX is greater than float_ty::MAX. Because - // we're rounding towards zero, we just get float_ty::MAX (which is always an integer). - // This already happens today with u128::MAX = 2^128 - 1 > f32::MAX. - let int_max = |signed: bool, int_width: u64| -> u128 { - let shift_amount = 128 - int_width; - if signed { i128::MAX as u128 >> shift_amount } else { u128::MAX >> shift_amount } - }; - let int_min = |signed: bool, int_width: u64| -> i128 { - if signed { i128::MIN >> (128 - int_width) } else { 0 } - }; - - let compute_clamp_bounds_single = |signed: bool, int_width: u64| -> (u128, u128) { - let rounded_min = - ieee::Single::from_i128_r(int_min(signed, int_width), Round::TowardZero); - assert_eq!(rounded_min.status, Status::OK); - let rounded_max = - ieee::Single::from_u128_r(int_max(signed, int_width), Round::TowardZero); - assert!(rounded_max.value.is_finite()); - (rounded_min.value.to_bits(), rounded_max.value.to_bits()) - }; - let compute_clamp_bounds_double = |signed: bool, int_width: u64| -> (u128, u128) { - let rounded_min = - ieee::Double::from_i128_r(int_min(signed, int_width), Round::TowardZero); - assert_eq!(rounded_min.status, Status::OK); - let rounded_max = - ieee::Double::from_u128_r(int_max(signed, int_width), Round::TowardZero); - assert!(rounded_max.value.is_finite()); - (rounded_min.value.to_bits(), rounded_max.value.to_bits()) - }; - // To implement saturation, we perform the following steps: - // - // 1. Cast x to an integer with fpto[su]i. This may result in undef. - // 2. Compare x to f_min and f_max, and use the comparison results to select: - // a) int_ty::MIN if x < f_min or x is NaN - // b) int_ty::MAX if x > f_max - // c) the result of fpto[su]i otherwise - // 3. If x is NaN, return 0.0, otherwise return the result of step 2. - // - // This avoids resulting undef because values in range [f_min, f_max] by definition fit into the - // destination type. It creates an undef temporary, but *producing* undef is not UB. Our use of - // undef does not introduce any non-determinism either. - // More importantly, the above procedure correctly implements saturating conversion. - // Proof (sketch): - // If x is NaN, 0 is returned by definition. - // Otherwise, x is finite or infinite and thus can be compared with f_min and f_max. - // This yields three cases to consider: - // (1) if x in [f_min, f_max], the result of fpto[su]i is returned, which agrees with - // saturating conversion for inputs in that range. - // (2) if x > f_max, then x is larger than int_ty::MAX. This holds even if f_max is rounded - // (i.e., if f_max < int_ty::MAX) because in those cases, nextUp(f_max) is already larger - // than int_ty::MAX. Because x is larger than int_ty::MAX, the return value of int_ty::MAX - // is correct. - // (3) if x < f_min, then x is smaller than int_ty::MIN. As shown earlier, f_min exactly equals - // int_ty::MIN and therefore the return value of int_ty::MIN is correct. - // QED. - - let float_bits_to_llval = |bx: &mut Self, bits| { - let bits_llval = match float_width { - 32 => bx.cx().const_u32(bits as u32), - 64 => bx.cx().const_u64(bits as u64), - n => bug!("unsupported float width {}", n), - }; - bx.bitcast(bits_llval, float_ty) - }; - let (f_min, f_max) = match float_width { - 32 => compute_clamp_bounds_single(signed, int_width), - 64 => compute_clamp_bounds_double(signed, int_width), - n => bug!("unsupported float width {}", n), - }; - let f_min = float_bits_to_llval(self, f_min); - let f_max = float_bits_to_llval(self, f_max); - let int_max = self.cx().const_uint_big(int_ty, int_max(signed, int_width)); - let int_min = self.cx().const_uint_big(int_ty, int_min(signed, int_width) as u128); - let zero = self.cx().const_uint(int_ty, 0); - - // If we're working with vectors, constants must be "splatted": the constant is duplicated - // into each lane of the vector. The algorithm stays the same, we are just using the - // same constant across all lanes. - let maybe_splat = |bx: &mut Self, val| { - if bx.cx().type_kind(dest_ty) == TypeKind::Vector { - bx.vector_splat(bx.vector_length(dest_ty), val) - } else { - val - } - }; - let f_min = maybe_splat(self, f_min); - let f_max = maybe_splat(self, f_max); - let int_max = maybe_splat(self, int_max); - let int_min = maybe_splat(self, int_min); - let zero = maybe_splat(self, zero); - - // Step 1 ... - let fptosui_result = if signed { self.fptosi(x, dest_ty) } else { self.fptoui(x, dest_ty) }; - let less_or_nan = self.fcmp(RealPredicate::RealULT, x, f_min); - let greater = self.fcmp(RealPredicate::RealOGT, x, f_max); - - // Step 2: We use two comparisons and two selects, with %s1 being the - // result: - // %less_or_nan = fcmp ult %x, %f_min - // %greater = fcmp olt %x, %f_max - // %s0 = select %less_or_nan, int_ty::MIN, %fptosi_result - // %s1 = select %greater, int_ty::MAX, %s0 - // Note that %less_or_nan uses an *unordered* comparison. This - // comparison is true if the operands are not comparable (i.e., if x is - // NaN). The unordered comparison ensures that s1 becomes int_ty::MIN if - // x is NaN. - // - // Performance note: Unordered comparison can be lowered to a "flipped" - // comparison and a negation, and the negation can be merged into the - // select. Therefore, it not necessarily any more expensive than an - // ordered ("normal") comparison. Whether these optimizations will be - // performed is ultimately up to the backend, but at least x86 does - // perform them. - let s0 = self.select(less_or_nan, int_min, fptosui_result); - let s1 = self.select(greater, int_max, s0); - - // Step 3: NaN replacement. - // For unsigned types, the above step already yielded int_ty::MIN == 0 if x is NaN. - // Therefore we only need to execute this step for signed integer types. - if signed { - // LLVM has no isNaN predicate, so we use (x == x) instead - let cmp = self.fcmp(RealPredicate::RealOEQ, x, x); - self.select(cmp, s1, zero) - } else { - s1 - } + if signed { self.fptosi_sat(x, dest_ty) } else { self.fptoui_sat(x, dest_ty) } } fn icmp(&mut self, op: IntPredicate, lhs: Self::Value, rhs: Self::Value) -> Self::Value; -- cgit 1.4.1-3-g733a5 From 0ff8f0b5782e736f75be6f36765791164d9f0db7 Mon Sep 17 00:00:00 2001 From: Alex <58638691+Alex-Velez@users.noreply.github.com> Date: Sun, 14 Aug 2022 21:06:01 -0500 Subject: Update src/test/assembly/x86_64-floating-point-clamp.rs Simple Clamp Function I thought this was more robust and easier to read. I also allowed this function to return early in order to skip the extra bound check (I'm sure the difference is negligible). I'm not sure if there was a reason for binding `self` to `x`; if so, please correct me. Simple Clamp Function for f64 I thought this was more robust and easier to read. I also allowed this function to return early in order to skip the extra bound check (I'm sure the difference is negligible). I'm not sure if there was a reason for binding `self` to `x`; if so, please correct me. Floating point clamp test f32 clamp using mut self f64 clamp using mut self Update library/core/src/num/f32.rs Update f64.rs Update x86_64-floating-point-clamp.rs Update src/test/assembly/x86_64-floating-point-clamp.rs Update x86_64-floating-point-clamp.rs Co-Authored-By: scottmcm --- library/core/src/num/f32.rs | 13 ++++++------ library/core/src/num/f64.rs | 13 ++++++------ src/test/assembly/x86_64-floating-point-clamp.rs | 25 ++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 14 deletions(-) create mode 100644 src/test/assembly/x86_64-floating-point-clamp.rs diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 6548ad2e514..f485e459121 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -1282,15 +1282,14 @@ impl f32 { #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "clamp", since = "1.50.0")] #[inline] - pub fn clamp(self, min: f32, max: f32) -> f32 { + pub fn clamp(mut self, min: f32, max: f32) -> f32 { assert!(min <= max); - let mut x = self; - if x < min { - x = min; + if self < min { + self = min; } - if x > max { - x = max; + if self > max { + self = max; } - x + self } } diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 75c92c2f883..3d385e3888a 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -1280,15 +1280,14 @@ impl f64 { #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "clamp", since = "1.50.0")] #[inline] - pub fn clamp(self, min: f64, max: f64) -> f64 { + pub fn clamp(mut self, min: f64, max: f64) -> f64 { assert!(min <= max); - let mut x = self; - if x < min { - x = min; + if self < min { + self = min; } - if x > max { - x = max; + if self > max { + self = max; } - x + self } } diff --git a/src/test/assembly/x86_64-floating-point-clamp.rs b/src/test/assembly/x86_64-floating-point-clamp.rs new file mode 100644 index 00000000000..3388b0e1abd --- /dev/null +++ b/src/test/assembly/x86_64-floating-point-clamp.rs @@ -0,0 +1,25 @@ +// Floating-point clamp is designed to be implementable as max+min, +// so check to make sure that's what it's actually emitting. + +// assembly-output: emit-asm +// compile-flags: --crate-type=lib -O -C llvm-args=-x86-asm-syntax=intel +// only-x86_64 + +// CHECK-LABEL: clamp_demo: +#[no_mangle] +pub fn clamp_demo(a: f32, x: f32, y: f32) -> f32 { + // CHECK: maxss + // CHECK: minss + a.clamp(x, y) +} + +// CHECK-LABEL: clamp12_demo: +#[no_mangle] +pub fn clamp12_demo(a: f32) -> f32 { + // CHECK-NEXT: movss xmm1 + // CHECK-NEXT: maxss xmm1, xmm0 + // CHECK-NEXT: movss xmm0 + // CHECK-NEXT: minss xmm0, xmm1 + // CHECK-NEXT: ret + a.clamp(1.0, 2.0) +} -- cgit 1.4.1-3-g733a5 From 302689fa7bbfc9b24b0bc73db41f7fce5586987c Mon Sep 17 00:00:00 2001 From: Alex <58638691+Alex-Velez@users.noreply.github.com> Date: Tue, 16 Aug 2022 20:39:22 -0500 Subject: Update src/test/assembly/x86_64-floating-point-clamp.rs Co-authored-by: scottmcm --- src/test/assembly/x86_64-floating-point-clamp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/assembly/x86_64-floating-point-clamp.rs b/src/test/assembly/x86_64-floating-point-clamp.rs index 3388b0e1abd..4493791a576 100644 --- a/src/test/assembly/x86_64-floating-point-clamp.rs +++ b/src/test/assembly/x86_64-floating-point-clamp.rs @@ -16,7 +16,7 @@ pub fn clamp_demo(a: f32, x: f32, y: f32) -> f32 { // CHECK-LABEL: clamp12_demo: #[no_mangle] pub fn clamp12_demo(a: f32) -> f32 { - // CHECK-NEXT: movss xmm1 + // CHECK: movss xmm1 // CHECK-NEXT: maxss xmm1, xmm0 // CHECK-NEXT: movss xmm0 // CHECK-NEXT: minss xmm0, xmm1 -- cgit 1.4.1-3-g733a5 From 5e1730fd17145fd9db5c042b127e2f400c83738a Mon Sep 17 00:00:00 2001 From: ltdk Date: Wed, 17 Aug 2022 02:01:32 -0400 Subject: Make slice::reverse const --- library/core/src/slice/mod.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index e79d47c9f98..361862cdd52 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -674,8 +674,9 @@ impl [T] { /// assert!(v == [3, 2, 1]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_reverse", issue = "none")] #[inline] - pub fn reverse(&mut self) { + pub const fn reverse(&mut self) { let half_len = self.len() / 2; let Range { start, end } = self.as_mut_ptr_range(); @@ -698,9 +699,9 @@ impl [T] { revswap(front_half, back_half, half_len); #[inline] - fn revswap(a: &mut [T], b: &mut [T], n: usize) { - debug_assert_eq!(a.len(), n); - debug_assert_eq!(b.len(), n); + const fn revswap(a: &mut [T], b: &mut [T], n: usize) { + debug_assert!(a.len() == n); + debug_assert!(b.len() == n); // Because this function is first compiled in isolation, // this check tells LLVM that the indexing below is @@ -708,8 +709,10 @@ impl [T] { // lengths of the slices are known -- it's removed. let (a, b) = (&mut a[..n], &mut b[..n]); - for i in 0..n { + let mut i = 0; + while i < n { mem::swap(&mut a[i], &mut b[n - 1 - i]); + i += 1; } } } -- cgit 1.4.1-3-g733a5 From 557c5b4dc57cb0fd5455bec35f2a97a4626e3df1 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 17 Aug 2022 09:32:25 +0200 Subject: minor: Change tracing event level in apply_change --- crates/ide-db/src/apply_change.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ide-db/src/apply_change.rs b/crates/ide-db/src/apply_change.rs index f8134c552f7..b1ee9b58d5b 100644 --- a/crates/ide-db/src/apply_change.rs +++ b/crates/ide-db/src/apply_change.rs @@ -20,7 +20,7 @@ impl RootDatabase { pub fn apply_change(&mut self, change: Change) { let _p = profile::span("RootDatabase::apply_change"); self.request_cancellation(); - tracing::info!("apply_change {:?}", change); + tracing::trace!("apply_change {:?}", change); if let Some(roots) = &change.roots { let mut local_roots = FxHashSet::default(); let mut library_roots = FxHashSet::default(); -- cgit 1.4.1-3-g733a5 From 2a23d08aaefd60d294d63600a707575a6efcf292 Mon Sep 17 00:00:00 2001 From: Raoul Strackx Date: Wed, 10 Aug 2022 15:38:53 +0200 Subject: Mitigate Stale Data Read for xAPIC vulnerability In order to mitigate the Stale Data Read for xAPIC vulnerability completely, reading userspace from an SGX enclave must be aligned and in 8-bytes chunks. References: - https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00657.html - https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/advisory-guidance/stale-data-read-from-xapic.html --- library/std/src/sys/sgx/abi/usercalls/alloc.rs | 114 +++++++++++++++++++++++-- library/std/src/sys/sgx/abi/usercalls/tests.rs | 30 ++++++- 2 files changed, 137 insertions(+), 7 deletions(-) diff --git a/library/std/src/sys/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/sgx/abi/usercalls/alloc.rs index a3b90fc7d80..34634da44de 100644 --- a/library/std/src/sys/sgx/abi/usercalls/alloc.rs +++ b/library/std/src/sys/sgx/abi/usercalls/alloc.rs @@ -313,9 +313,9 @@ where // +--------+ // | small1 | Chunk smaller than 8 bytes // +--------+ -fn region_as_aligned_chunks(ptr: *const u8, len: usize) -> (u8, usize, u8) { - let small0_size = (8 - ptr as usize % 8) as u8; - let small1_size = ((len - small0_size as usize) % 8) as u8; +fn region_as_aligned_chunks(ptr: *const u8, len: usize) -> (usize, usize, usize) { + let small0_size = if ptr as usize % 8 == 0 { 0 } else { 8 - ptr as usize % 8 }; + let small1_size = (len - small0_size as usize) % 8; let big_size = len - small0_size as usize - small1_size as usize; (small0_size, big_size, small1_size) @@ -417,6 +417,106 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize) } } +/// Copies `len` bytes of data from userspace pointer `src` to enclave pointer `dst` +/// +/// This function mitigates AEPIC leak vulnerabilities by ensuring all reads from untrusted memory are 8-byte aligned +/// +/// # Panics +/// This function panics if: +/// +/// * The `src` pointer is null +/// * The `dst` pointer is null +/// * The `src` memory range is not in user memory +/// * The `dst` memory range is not in enclave memory +/// +/// # References +/// - https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00657.html +/// - https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/advisory-guidance/stale-data-read-from-xapic.html +pub(crate) unsafe fn copy_from_userspace(src: *const u8, dst: *mut u8, len: usize) { + // Copies memory region `src..src + len` to the enclave at `dst`. The source memory region + // is: + // - strictly less than 8 bytes in size and may be + // - located at a misaligned memory location + fn copy_misaligned_chunk_to_enclave(src: *const u8, dst: *mut u8, len: usize) { + let mut tmp_buff = [0u8; 16]; + + unsafe { + // Compute an aligned memory region to read from + // +--------+ <-- aligned_src + aligned_len (8B-aligned) + // | pad1 | + // +--------+ <-- src + len (misaligned) + // | | + // | | + // | | + // +--------+ <-- src (misaligned) + // | pad0 | + // +--------+ <-- aligned_src (8B-aligned) + let pad0_size = src as usize % 8; + let aligned_src = src.sub(pad0_size); + + let pad1_size = 8 - (src.add(len) as usize % 8); + let aligned_len = pad0_size + len + pad1_size; + + debug_assert!(len < 8); + debug_assert_eq!(aligned_src as usize % 8, 0); + debug_assert_eq!(aligned_len % 8, 0); + debug_assert!(aligned_len <= 16); + + // Copy the aligned buffer to a temporary buffer + // Note: copying from a slightly different memory location is a bit odd. In this case it + // can't lead to page faults or inadvertent copying from the enclave as we only ensured + // that the `src` pointer is aligned at an 8 byte boundary. As pages are 4096 bytes + // aligned, `aligned_src` must be on the same page as `src`. A similar argument can be made + // for `src + len` + copy_quadwords(aligned_src as _, tmp_buff.as_mut_ptr(), aligned_len); + + // Copy the correct parts of the temporary buffer to the destination + ptr::copy(tmp_buff.as_ptr().add(pad0_size), dst, len); + } + } + + assert!(!src.is_null()); + assert!(!dst.is_null()); + assert!(is_user_range(src, len)); + assert!(is_enclave_range(dst, len)); + assert!(!(src as usize).overflowing_add(len + 8).1); + assert!(!(dst as usize).overflowing_add(len + 8).1); + + if len < 8 { + copy_misaligned_chunk_to_enclave(src, dst, len); + } else if len % 8 == 0 && src as usize % 8 == 0 { + // Copying 8-byte aligned quadwords: copy quad word per quad word + unsafe { + copy_quadwords(src, dst, len); + } + } else { + // Split copies into three parts: + // +--------+ + // | small0 | Chunk smaller than 8 bytes + // +--------+ + // | big | Chunk 8-byte aligned, and size a multiple of 8 bytes + // +--------+ + // | small1 | Chunk smaller than 8 bytes + // +--------+ + let (small0_size, big_size, small1_size) = region_as_aligned_chunks(dst, len); + + unsafe { + // Copy small0 + copy_misaligned_chunk_to_enclave(src, dst, small0_size); + + // Copy big + let big_src = src.add(small0_size); + let big_dst = dst.add(small0_size); + copy_quadwords(big_src, big_dst, big_size); + + // Copy small1 + let small1_src = src.add(big_size + small0_size); + let small1_dst = dst.add(big_size + small0_size); + copy_misaligned_chunk_to_enclave(small1_src, small1_dst, small1_size); + } + } +} + #[unstable(feature = "sgx_platform", issue = "56975")] impl UserRef where @@ -481,7 +581,7 @@ where pub fn copy_to_enclave(&self, dest: &mut T) { unsafe { assert_eq!(mem::size_of_val(dest), mem::size_of_val(&*self.0.get())); - ptr::copy( + copy_from_userspace( self.0.get() as *const T as *const u8, dest as *mut T as *mut u8, mem::size_of_val(dest), @@ -507,7 +607,11 @@ where { /// Copies the value from user memory into enclave memory. pub fn to_enclave(&self) -> T { - unsafe { ptr::read(self.0.get()) } + unsafe { + let mut data: T = mem::MaybeUninit::uninit().assume_init(); + copy_from_userspace(self.0.get() as _, &mut data as *mut T as _, mem::size_of::()); + data + } } } diff --git a/library/std/src/sys/sgx/abi/usercalls/tests.rs b/library/std/src/sys/sgx/abi/usercalls/tests.rs index cbf7d7d54f7..4320f0bccd1 100644 --- a/library/std/src/sys/sgx/abi/usercalls/tests.rs +++ b/library/std/src/sys/sgx/abi/usercalls/tests.rs @@ -1,8 +1,8 @@ -use super::alloc::copy_to_userspace; use super::alloc::User; +use super::alloc::{copy_from_userspace, copy_to_userspace}; #[test] -fn test_copy_function() { +fn test_copy_to_userspace_function() { let mut src = [0u8; 100]; let mut dst = User::<[u8]>::uninitialized(100); @@ -28,3 +28,29 @@ fn test_copy_function() { } } } + +#[test] +fn test_copy_from_userspace_function() { + let mut dst = [0u8; 100]; + let mut src = User::<[u8]>::uninitialized(100); + + src.copy_from_enclave(&[0u8; 100]); + + for size in 0..48 { + // For all possible alignment + for offset in 0..8 { + // overwrite complete dst + dst = [0u8; 100]; + + // Copy src[0..size] to dst + offset + unsafe { copy_from_userspace(src.as_ptr().offset(offset), dst.as_mut_ptr(), size) }; + + // Verify copy + for byte in 0..size { + unsafe { + assert_eq!(dst[byte as usize], *src.as_ptr().offset(offset + byte as isize)); + } + } + } + } +} -- cgit 1.4.1-3-g733a5 From 7cba1f9eab463738f6b3530597cae76cd8bc4dc0 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Tue, 16 Aug 2022 13:02:45 +0000 Subject: llvm-wrapper: use new pass manager for thin lto with LLVM version 15 No functional changes intended. LLVM commit https://github.com/llvm/llvm-project/commit/633f5663c37a670e28040cadd938200abd854483 removed `createWriteThinLTOBitcodePass`. This adapts PassWrapper similarly to the example mentioned upstream: https://github.com/llvm/llvm-project/commit/633f5663c37a670e28040cadd938200abd854483. --- compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 25 ++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index b4314223722..05d2a214d0b 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -31,6 +31,9 @@ #include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" #include "llvm/Transforms/IPO/FunctionImport.h" +#if LLVM_VERSION_GE(15, 0) +#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h" +#endif #include "llvm/Transforms/Utils/AddDiscriminators.h" #include "llvm/Transforms/Utils/FunctionImportUtils.h" #include "llvm/LTO/LTO.h" @@ -1587,13 +1590,31 @@ LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin) { { raw_string_ostream OS(Ret->data); { - legacy::PassManager PM; if (is_thin) { +#if LLVM_VERSION_LT(15, 0) + legacy::PassManager PM; PM.add(createWriteThinLTOBitcodePass(OS)); + PM.run(*unwrap(M)); +#else + PassBuilder PB; + LoopAnalysisManager LAM; + FunctionAnalysisManager FAM; + CGSCCAnalysisManager CGAM; + ModuleAnalysisManager MAM; + PB.registerModuleAnalyses(MAM); + PB.registerCGSCCAnalyses(CGAM); + PB.registerFunctionAnalyses(FAM); + PB.registerLoopAnalyses(LAM); + PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); + ModulePassManager MPM; + MPM.addPass(ThinLTOBitcodeWriterPass(OS, nullptr)); + MPM.run(*unwrap(M), MAM); +#endif } else { + legacy::PassManager PM; PM.add(createBitcodeWriterPass(OS)); + PM.run(*unwrap(M)); } - PM.run(*unwrap(M)); } } return Ret.release(); -- cgit 1.4.1-3-g733a5 From b7a8496a073c7ee1a8b4bb9dc4ee4efed80e3522 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 17 Aug 2022 11:22:47 +0200 Subject: add List::as_slice --- compiler/rustc_middle/src/ty/list.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs index db3b5cfd180..79365ef281b 100644 --- a/compiler/rustc_middle/src/ty/list.rs +++ b/compiler/rustc_middle/src/ty/list.rs @@ -65,6 +65,10 @@ impl List { pub fn len(&self) -> usize { self.len } + + pub fn as_slice(&self) -> &[T] { + self + } } impl List { -- cgit 1.4.1-3-g733a5 From 7b457184849d343d50a3eb56c28396189c696a42 Mon Sep 17 00:00:00 2001 From: ouz-a Date: Sat, 13 Aug 2022 18:13:20 +0300 Subject: pass when where clause found --- compiler/rustc_typeck/src/check/writeback.rs | 26 +++++++++++- src/test/mir-opt/issue-91633.rs | 31 ++++++++++++++ src/test/mir-opt/issue_91633.bar.mir_map.0.mir | 39 ++++++++++++++++++ src/test/mir-opt/issue_91633.foo.mir_map.0.mir | 57 ++++++++++++++++++++++++++ src/test/mir-opt/issue_91633.fun.mir_map.0.mir | 35 ++++++++++++++++ src/test/mir-opt/issue_91633.hey.mir_map.0.mir | 35 ++++++++++++++++ src/test/ui/typeck/issue-91633.rs | 8 ++++ 7 files changed, 229 insertions(+), 2 deletions(-) create mode 100644 src/test/mir-opt/issue-91633.rs create mode 100644 src/test/mir-opt/issue_91633.bar.mir_map.0.mir create mode 100644 src/test/mir-opt/issue_91633.foo.mir_map.0.mir create mode 100644 src/test/mir-opt/issue_91633.fun.mir_map.0.mir create mode 100644 src/test/mir-opt/issue_91633.hey.mir_map.0.mir create mode 100644 src/test/ui/typeck/issue-91633.rs diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index f549807c39c..adcf8ff946d 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -3,7 +3,6 @@ // substitutions. use crate::check::FnCtxt; - use hir::def_id::LocalDefId; use rustc_data_structures::fx::FxHashMap; use rustc_errors::ErrorGuaranteed; @@ -16,6 +15,7 @@ use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable}; +use rustc_middle::ty::TypeckResults; use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt}; use rustc_span::symbol::sym; use rustc_span::Span; @@ -192,6 +192,27 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } + // (ouz-a 1005988): Normally `[T] : std::ops::Index` should be normalized + // into [T] but currently `Where` clause stops the normalization process for it, + // here we compare types of expr and base in a code without `Where` clause they would be equal + // if they are not we don't modify the expr, hence we bypass the ICE + fn is_builtin_index( + &mut self, + typeck_results: &TypeckResults<'tcx>, + e: &hir::Expr<'_>, + base_ty: Ty<'tcx>, + index_ty: Ty<'tcx>, + ) -> bool { + if let Some(elem_ty) = base_ty.builtin_index() { + let Some(exp_ty) = typeck_results.expr_ty_opt(e) else {return false;}; + let resolved_exp_ty = self.resolve(exp_ty, &e.span); + + elem_ty == resolved_exp_ty && index_ty == self.fcx.tcx.types.usize + } else { + false + } + } + // Similar to operators, indexing is always assumed to be overloaded // Here, correct cases where an indexing expression can be simplified // to use builtin indexing because the index type is known to be @@ -222,8 +243,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { ) }); let index_ty = self.fcx.resolve_vars_if_possible(index_ty); + let resolved_base_ty = self.resolve(*base_ty, &base.span); - if base_ty.builtin_index().is_some() && index_ty == self.fcx.tcx.types.usize { + if self.is_builtin_index(&typeck_results, e, resolved_base_ty, index_ty) { // Remove the method call record typeck_results.type_dependent_defs_mut().remove(e.hir_id); typeck_results.node_substs_mut().remove(e.hir_id); diff --git a/src/test/mir-opt/issue-91633.rs b/src/test/mir-opt/issue-91633.rs new file mode 100644 index 00000000000..8f66019857f --- /dev/null +++ b/src/test/mir-opt/issue-91633.rs @@ -0,0 +1,31 @@ +// compile-flags: -Z mir-opt-level=0 +// EMIT_MIR issue_91633.hey.mir_map.0.mir +fn hey (it: &[T]) + where + [T] : std::ops::Index, + { + let _ = &it[0]; + } + +// EMIT_MIR issue_91633.bar.mir_map.0.mir +fn bar (it: Box<[T]>) + where + [T] : std::ops::Index, + { + let _ = it[0]; + } + +// EMIT_MIR issue_91633.fun.mir_map.0.mir +fn fun (it: &[T]) -> &T + { + let f = &it[0]; + f + } + +// EMIT_MIR issue_91633.foo.mir_map.0.mir +fn foo (it: Box<[T]>) -> T + { + let f = it[0].clone(); + f + } + fn main(){} diff --git a/src/test/mir-opt/issue_91633.bar.mir_map.0.mir b/src/test/mir-opt/issue_91633.bar.mir_map.0.mir new file mode 100644 index 00000000000..f5092d2ac92 --- /dev/null +++ b/src/test/mir-opt/issue_91633.bar.mir_map.0.mir @@ -0,0 +1,39 @@ +// MIR for `bar` 0 mir_map + +fn bar(_1: Box<[T]>) -> () { + debug it => _1; // in scope 0 at $DIR/issue-91633.rs:+0:12: +0:14 + let mut _0: (); // return place in scope 0 at $DIR/issue-91633.rs:+1:2: +1:2 + let mut _2: &<[T] as std::ops::Index>::Output; // in scope 0 at $DIR/issue-91633.rs:+4:14: +4:19 + let mut _3: &[T]; // in scope 0 at $DIR/issue-91633.rs:+4:14: +4:16 + scope 1 { + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue-91633.rs:+4:14: +4:19 + StorageLive(_3); // scope 0 at $DIR/issue-91633.rs:+4:14: +4:16 + _3 = &(*_1); // scope 0 at $DIR/issue-91633.rs:+4:14: +4:16 + _2 = <[T] as Index>::index(move _3, const 0_usize) -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/issue-91633.rs:+4:14: +4:19 + // mir::Constant + // + span: $DIR/issue-91633.rs:15:14: 15:19 + // + literal: Const { ty: for<'r> fn(&'r [T], usize) -> &'r <[T] as Index>::Output {<[T] as Index>::index}, val: Value() } + } + + bb1: { + StorageDead(_3); // scope 0 at $DIR/issue-91633.rs:+4:18: +4:19 + StorageDead(_2); // scope 0 at $DIR/issue-91633.rs:+4:19: +4:20 + _0 = const (); // scope 0 at $DIR/issue-91633.rs:+3:2: +5:3 + drop(_1) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-91633.rs:+5:2: +5:3 + } + + bb2: { + return; // scope 0 at $DIR/issue-91633.rs:+5:3: +5:3 + } + + bb3 (cleanup): { + drop(_1) -> bb4; // scope 0 at $DIR/issue-91633.rs:+5:2: +5:3 + } + + bb4 (cleanup): { + resume; // scope 0 at $DIR/issue-91633.rs:+0:1: +5:3 + } +} diff --git a/src/test/mir-opt/issue_91633.foo.mir_map.0.mir b/src/test/mir-opt/issue_91633.foo.mir_map.0.mir new file mode 100644 index 00000000000..2e8b0feedd3 --- /dev/null +++ b/src/test/mir-opt/issue_91633.foo.mir_map.0.mir @@ -0,0 +1,57 @@ +// MIR for `foo` 0 mir_map + +fn foo(_1: Box<[T]>) -> T { + debug it => _1; // in scope 0 at $DIR/issue-91633.rs:+0:19: +0:21 + let mut _0: T; // return place in scope 0 at $DIR/issue-91633.rs:+0:36: +0:37 + let _2: T; // in scope 0 at $DIR/issue-91633.rs:+2:10: +2:11 + let mut _3: &T; // in scope 0 at $DIR/issue-91633.rs:+2:14: +2:27 + let _4: usize; // in scope 0 at $DIR/issue-91633.rs:+2:17: +2:18 + let mut _5: usize; // in scope 0 at $DIR/issue-91633.rs:+2:14: +2:19 + let mut _6: bool; // in scope 0 at $DIR/issue-91633.rs:+2:14: +2:19 + scope 1 { + debug f => _2; // in scope 1 at $DIR/issue-91633.rs:+2:10: +2:11 + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue-91633.rs:+2:10: +2:11 + StorageLive(_3); // scope 0 at $DIR/issue-91633.rs:+2:14: +2:27 + StorageLive(_4); // scope 0 at $DIR/issue-91633.rs:+2:17: +2:18 + _4 = const 0_usize; // scope 0 at $DIR/issue-91633.rs:+2:17: +2:18 + _5 = Len((*_1)); // scope 0 at $DIR/issue-91633.rs:+2:14: +2:19 + _6 = Lt(_4, _5); // scope 0 at $DIR/issue-91633.rs:+2:14: +2:19 + assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind: bb5]; // scope 0 at $DIR/issue-91633.rs:+2:14: +2:19 + } + + bb1: { + _3 = &(*_1)[_4]; // scope 0 at $DIR/issue-91633.rs:+2:14: +2:27 + _2 = ::clone(move _3) -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/issue-91633.rs:+2:14: +2:27 + // mir::Constant + // + span: $DIR/issue-91633.rs:28:20: 28:25 + // + literal: Const { ty: for<'r> fn(&'r T) -> T {::clone}, val: Value() } + } + + bb2: { + StorageDead(_3); // scope 0 at $DIR/issue-91633.rs:+2:26: +2:27 + FakeRead(ForLet(None), _2); // scope 0 at $DIR/issue-91633.rs:+2:10: +2:11 + StorageDead(_4); // scope 0 at $DIR/issue-91633.rs:+2:27: +2:28 + _0 = move _2; // scope 1 at $DIR/issue-91633.rs:+3:6: +3:7 + drop(_2) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3 + } + + bb3: { + StorageDead(_2); // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3 + drop(_1) -> [return: bb4, unwind: bb6]; // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3 + } + + bb4: { + return; // scope 0 at $DIR/issue-91633.rs:+4:3: +4:3 + } + + bb5 (cleanup): { + drop(_1) -> bb6; // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3 + } + + bb6 (cleanup): { + resume; // scope 0 at $DIR/issue-91633.rs:+0:1: +4:3 + } +} diff --git a/src/test/mir-opt/issue_91633.fun.mir_map.0.mir b/src/test/mir-opt/issue_91633.fun.mir_map.0.mir new file mode 100644 index 00000000000..ded9a4cf7e3 --- /dev/null +++ b/src/test/mir-opt/issue_91633.fun.mir_map.0.mir @@ -0,0 +1,35 @@ +// MIR for `fun` 0 mir_map + +fn fun(_1: &[T]) -> &T { + debug it => _1; // in scope 0 at $DIR/issue-91633.rs:+0:12: +0:14 + let mut _0: &T; // return place in scope 0 at $DIR/issue-91633.rs:+0:25: +0:27 + let _2: &T; // in scope 0 at $DIR/issue-91633.rs:+2:10: +2:11 + let _3: usize; // in scope 0 at $DIR/issue-91633.rs:+2:18: +2:19 + let mut _4: usize; // in scope 0 at $DIR/issue-91633.rs:+2:15: +2:20 + let mut _5: bool; // in scope 0 at $DIR/issue-91633.rs:+2:15: +2:20 + scope 1 { + debug f => _2; // in scope 1 at $DIR/issue-91633.rs:+2:10: +2:11 + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue-91633.rs:+2:10: +2:11 + StorageLive(_3); // scope 0 at $DIR/issue-91633.rs:+2:18: +2:19 + _3 = const 0_usize; // scope 0 at $DIR/issue-91633.rs:+2:18: +2:19 + _4 = Len((*_1)); // scope 0 at $DIR/issue-91633.rs:+2:15: +2:20 + _5 = Lt(_3, _4); // scope 0 at $DIR/issue-91633.rs:+2:15: +2:20 + assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind: bb2]; // scope 0 at $DIR/issue-91633.rs:+2:15: +2:20 + } + + bb1: { + _2 = &(*_1)[_3]; // scope 0 at $DIR/issue-91633.rs:+2:14: +2:20 + FakeRead(ForLet(None), _2); // scope 0 at $DIR/issue-91633.rs:+2:10: +2:11 + _0 = &(*_2); // scope 1 at $DIR/issue-91633.rs:+3:6: +3:7 + StorageDead(_3); // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3 + StorageDead(_2); // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3 + return; // scope 0 at $DIR/issue-91633.rs:+4:3: +4:3 + } + + bb2 (cleanup): { + resume; // scope 0 at $DIR/issue-91633.rs:+0:1: +4:3 + } +} diff --git a/src/test/mir-opt/issue_91633.hey.mir_map.0.mir b/src/test/mir-opt/issue_91633.hey.mir_map.0.mir new file mode 100644 index 00000000000..74f4a5a9761 --- /dev/null +++ b/src/test/mir-opt/issue_91633.hey.mir_map.0.mir @@ -0,0 +1,35 @@ +// MIR for `hey` 0 mir_map + +fn hey(_1: &[T]) -> () { + debug it => _1; // in scope 0 at $DIR/issue-91633.rs:+0:12: +0:14 + let mut _0: (); // return place in scope 0 at $DIR/issue-91633.rs:+1:2: +1:2 + let mut _2: &<[T] as std::ops::Index>::Output; // in scope 0 at $DIR/issue-91633.rs:+4:14: +4:20 + let _3: &<[T] as std::ops::Index>::Output; // in scope 0 at $DIR/issue-91633.rs:+4:15: +4:20 + let mut _4: &[T]; // in scope 0 at $DIR/issue-91633.rs:+4:15: +4:17 + scope 1 { + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue-91633.rs:+4:14: +4:20 + StorageLive(_3); // scope 0 at $DIR/issue-91633.rs:+4:15: +4:20 + StorageLive(_4); // scope 0 at $DIR/issue-91633.rs:+4:15: +4:17 + _4 = &(*_1); // scope 0 at $DIR/issue-91633.rs:+4:15: +4:17 + _3 = <[T] as Index>::index(move _4, const 0_usize) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/issue-91633.rs:+4:15: +4:20 + // mir::Constant + // + span: $DIR/issue-91633.rs:7:15: 7:20 + // + literal: Const { ty: for<'r> fn(&'r [T], usize) -> &'r <[T] as Index>::Output {<[T] as Index>::index}, val: Value() } + } + + bb1: { + StorageDead(_4); // scope 0 at $DIR/issue-91633.rs:+4:19: +4:20 + _2 = &(*_3); // scope 0 at $DIR/issue-91633.rs:+4:14: +4:20 + StorageDead(_2); // scope 0 at $DIR/issue-91633.rs:+4:20: +4:21 + _0 = const (); // scope 0 at $DIR/issue-91633.rs:+3:2: +5:3 + StorageDead(_3); // scope 0 at $DIR/issue-91633.rs:+5:2: +5:3 + return; // scope 0 at $DIR/issue-91633.rs:+5:3: +5:3 + } + + bb2 (cleanup): { + resume; // scope 0 at $DIR/issue-91633.rs:+0:1: +5:3 + } +} diff --git a/src/test/ui/typeck/issue-91633.rs b/src/test/ui/typeck/issue-91633.rs new file mode 100644 index 00000000000..331a798dd7a --- /dev/null +++ b/src/test/ui/typeck/issue-91633.rs @@ -0,0 +1,8 @@ +// check-pass +fn f (it: &[T]) +where + [T] : std::ops::Index, +{ + let _ = &it[0]; +} +fn main(){} -- cgit 1.4.1-3-g733a5 From a3409c3a83fb1d8139bac8b3e438f56f2ac633a3 Mon Sep 17 00:00:00 2001 From: Ryo Yoshida Date: Tue, 16 Aug 2022 10:08:45 +0900 Subject: fix: escape keywords used as names in earlier editions --- crates/hir-expand/src/name.rs | 10 ++++++++-- crates/ide-db/src/search.rs | 4 +++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs index 87c663eec8e..a1bb353374b 100644 --- a/crates/hir-expand/src/name.rs +++ b/crates/hir-expand/src/name.rs @@ -90,10 +90,16 @@ impl Name { /// Resolve a name from the text of token. fn resolve(raw_text: &str) -> Name { - // When `raw_text` starts with "r#" but the name does not coincide with any - // keyword, we never need the prefix so we strip it. match raw_text.strip_prefix("r#") { + // When `raw_text` starts with "r#" but the name does not coincide with any + // keyword, we never need the prefix so we strip it. Some(text) if !is_raw_identifier(text) => Name::new_text(SmolStr::new(text)), + // Keywords (in the current edition) *can* be used as a name in earlier editions of + // Rust, e.g. "try" in Rust 2015. Even in such cases, we keep track of them in their + // escaped form. + None if is_raw_identifier(raw_text) => { + Name::new_text(SmolStr::from_iter(["r#", raw_text])) + } _ => Name::new_text(raw_text.into()), } } diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs index 9eaabeec7a4..2f4aa113170 100644 --- a/crates/ide-db/src/search.rs +++ b/crates/ide-db/src/search.rs @@ -402,7 +402,9 @@ impl<'a> FindUsages<'a> { .or_else(|| ty.as_builtin().map(|builtin| builtin.name())) }) }; - self.def.name(sema.db).or_else(self_kw_refs).map(|it| it.to_smol_str()) + // We need to unescape the name in case it is written without "r#" in earlier + // editions of Rust where it isn't a keyword. + self.def.name(sema.db).or_else(self_kw_refs).map(|it| it.unescaped().to_smol_str()) } }; let name = match &name { -- cgit 1.4.1-3-g733a5 From 313b004ef76d3352f36e5128b16ca5212de97d49 Mon Sep 17 00:00:00 2001 From: Aleksandr Pak Date: Wed, 17 Aug 2022 12:50:33 +0300 Subject: fixup! feat: add inline_type_alias_uses assist --- crates/ide-assists/src/handlers/inline_type_alias.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ide-assists/src/handlers/inline_type_alias.rs b/crates/ide-assists/src/handlers/inline_type_alias.rs index c4e5bc9c7cb..9adf6381c1c 100644 --- a/crates/ide-assists/src/handlers/inline_type_alias.rs +++ b/crates/ide-assists/src/handlers/inline_type_alias.rs @@ -66,7 +66,7 @@ pub(crate) fn inline_type_alias_uses(acc: &mut Assists, ctx: &AssistContext<'_>) .into_iter() .filter_map(|file_ref| match file_ref.name { ast::NameLike::NameRef(path_type) => { - path_type.syntax().ancestors().find_map(ast::PathType::cast) + path_type.syntax().ancestors().nth(3).and_then(ast::PathType::cast) } _ => None, }) -- cgit 1.4.1-3-g733a5 From ddf23cbebaa74897a3b1d1f14463fe21b171fdeb Mon Sep 17 00:00:00 2001 From: ouz-a Date: Wed, 17 Aug 2022 13:21:03 +0300 Subject: add new test and combine old ones --- src/test/ui/or-patterns/inner-or-pat-2.rs | 13 ----- src/test/ui/or-patterns/inner-or-pat-2.stderr | 11 ---- src/test/ui/or-patterns/inner-or-pat-3.rs | 15 ------ src/test/ui/or-patterns/inner-or-pat-4.rs | 13 ----- src/test/ui/or-patterns/inner-or-pat-4.stderr | 11 ---- src/test/ui/or-patterns/inner-or-pat.or3.stderr | 11 ++++ src/test/ui/or-patterns/inner-or-pat.or4.stderr | 11 ++++ src/test/ui/or-patterns/inner-or-pat.rs | 67 +++++++++++++++++++++++-- 8 files changed, 85 insertions(+), 67 deletions(-) delete mode 100644 src/test/ui/or-patterns/inner-or-pat-2.rs delete mode 100644 src/test/ui/or-patterns/inner-or-pat-2.stderr delete mode 100644 src/test/ui/or-patterns/inner-or-pat-3.rs delete mode 100644 src/test/ui/or-patterns/inner-or-pat-4.rs delete mode 100644 src/test/ui/or-patterns/inner-or-pat-4.stderr create mode 100644 src/test/ui/or-patterns/inner-or-pat.or3.stderr create mode 100644 src/test/ui/or-patterns/inner-or-pat.or4.stderr diff --git a/src/test/ui/or-patterns/inner-or-pat-2.rs b/src/test/ui/or-patterns/inner-or-pat-2.rs deleted file mode 100644 index 3053d973453..00000000000 --- a/src/test/ui/or-patterns/inner-or-pat-2.rs +++ /dev/null @@ -1,13 +0,0 @@ -#[allow(unused_variables)] -#[allow(unused_parens)] -fn main() { - let x = "foo"; - match x { - x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | () | "nop") | ("hey" | "gg")) | - //~^ ERROR mismatched types - x @ ("black" | "pink") | - x @ ("red" | "blue") => { - } - _ => (), - } -} diff --git a/src/test/ui/or-patterns/inner-or-pat-2.stderr b/src/test/ui/or-patterns/inner-or-pat-2.stderr deleted file mode 100644 index 505b6c64a22..00000000000 --- a/src/test/ui/or-patterns/inner-or-pat-2.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/inner-or-pat-2.rs:6:54 - | -LL | match x { - | - this expression has type `&str` -LL | x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | () | "nop") | ("hey" | "gg")) | - | ^^ expected `str`, found `()` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/or-patterns/inner-or-pat-3.rs b/src/test/ui/or-patterns/inner-or-pat-3.rs deleted file mode 100644 index f6fe8a4dd59..00000000000 --- a/src/test/ui/or-patterns/inner-or-pat-3.rs +++ /dev/null @@ -1,15 +0,0 @@ -// run-pass - -#[allow(unreachable_patterns)] -#[allow(unused_variables)] -#[allow(unused_parens)] -fn main() { - let x = "foo"; - - match x { - x @ ("foo" | "bar") | - (x @ "red" | (x @ "blue" | x @ "red")) => { - } - _ => (), - } -} diff --git a/src/test/ui/or-patterns/inner-or-pat-4.rs b/src/test/ui/or-patterns/inner-or-pat-4.rs deleted file mode 100644 index fe771e2e930..00000000000 --- a/src/test/ui/or-patterns/inner-or-pat-4.rs +++ /dev/null @@ -1,13 +0,0 @@ -#[allow(unused_variables)] -#[allow(unused_parens)] -fn main() { - let x = "foo"; - - match x { - x @ ("foo" | "bar") | - (x @ "red" | (x @ "blue" | "red")) => { - //~^ variable `x` is not bound in all patterns - } - _ => (), - } -} diff --git a/src/test/ui/or-patterns/inner-or-pat-4.stderr b/src/test/ui/or-patterns/inner-or-pat-4.stderr deleted file mode 100644 index 177c7f98312..00000000000 --- a/src/test/ui/or-patterns/inner-or-pat-4.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0408]: variable `x` is not bound in all patterns - --> $DIR/inner-or-pat-4.rs:8:37 - | -LL | (x @ "red" | (x @ "blue" | "red")) => { - | - ^^^^^ pattern doesn't bind `x` - | | - | variable not in all patterns - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0408`. diff --git a/src/test/ui/or-patterns/inner-or-pat.or3.stderr b/src/test/ui/or-patterns/inner-or-pat.or3.stderr new file mode 100644 index 00000000000..2236a38c37b --- /dev/null +++ b/src/test/ui/or-patterns/inner-or-pat.or3.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/inner-or-pat.rs:38:54 + | +LL | match x { + | - this expression has type `&str` +LL | x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | () | "nop") | ("hey" | "gg")) | + | ^^ expected `str`, found `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/or-patterns/inner-or-pat.or4.stderr b/src/test/ui/or-patterns/inner-or-pat.or4.stderr new file mode 100644 index 00000000000..058873ff5ff --- /dev/null +++ b/src/test/ui/or-patterns/inner-or-pat.or4.stderr @@ -0,0 +1,11 @@ +error[E0408]: variable `x` is not bound in all patterns + --> $DIR/inner-or-pat.rs:53:37 + | +LL | (x @ "red" | (x @ "blue" | "red")) => { + | - ^^^^^ pattern doesn't bind `x` + | | + | variable not in all patterns + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0408`. diff --git a/src/test/ui/or-patterns/inner-or-pat.rs b/src/test/ui/or-patterns/inner-or-pat.rs index c49b04aa65b..f4cf4b0c188 100644 --- a/src/test/ui/or-patterns/inner-or-pat.rs +++ b/src/test/ui/or-patterns/inner-or-pat.rs @@ -1,8 +1,16 @@ -// run-pass +// revisions: or1 or2 or3 or4 or5 +// [or1] run-pass +// [or2] run-pass +// [or5] run-pass -#[allow(unused_variables)] -#[allow(unused_parens)] -fn main() { +#![allow(unreachable_patterns)] +#![allow(unused_variables)] +#![allow(unused_parens)] +#![allow(dead_code)] + + + +fn foo() { let x = "foo"; match x { x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | "no" | "nop") | ("hey" | "gg")) | @@ -12,3 +20,54 @@ fn main() { _ => (), } } + +fn bar() { + let x = "foo"; + match x { + x @ ("foo" | "bar") | + (x @ "red" | (x @ "blue" | x @ "red")) => { + } + _ => (), + } +} + +#[cfg(or3)] +fn zot() { + let x = "foo"; + match x { + x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | () | "nop") | ("hey" | "gg")) | + //[or3]~^ ERROR mismatched types + x @ ("black" | "pink") | + x @ ("red" | "blue") => { + } + _ => (), + } +} + + +#[cfg(or4)] +fn hey() { + let x = "foo"; + match x { + x @ ("foo" | "bar") | + (x @ "red" | (x @ "blue" | "red")) => { + //[or4]~^ variable `x` is not bound in all patterns + } + _ => (), + } +} + +fn don() { + enum Foo { + A, + B, + C, + } + + match Foo::A { + | _foo @ (Foo::A | Foo::B) => {} + Foo::C => {} + }; +} + +fn main(){} -- cgit 1.4.1-3-g733a5 From 4fe666ee64d9f2a73571f0ab74a29cd30190573e Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 17 Aug 2022 12:22:32 +0200 Subject: implied_bounds: clarify our assumptions --- compiler/rustc_middle/src/query/mod.rs | 8 ++ compiler/rustc_ty_utils/src/implied_bounds.rs | 60 +++++++++++++ compiler/rustc_ty_utils/src/lib.rs | 2 + compiler/rustc_typeck/src/check/compare_method.rs | 22 ++--- compiler/rustc_typeck/src/check/wfcheck.rs | 93 +++++--------------- .../src/impl_wf_check/min_specialization.rs | 99 ++++++++++++---------- .../associated-types-for-unimpl-trait.stderr | 4 +- .../associated-types-no-suitable-bound.stderr | 4 +- ...ssociated-types-no-suitable-supertrait-2.stderr | 4 +- .../associated-types-no-suitable-supertrait.stderr | 8 +- ...nrelated-trait-in-method-without-default.stderr | 4 +- src/test/ui/associated-types/issue-59324.stderr | 14 +-- src/test/ui/issues/issue-18611.stderr | 8 +- src/test/ui/issues/issue-20831-debruijn.stderr | 24 ++++-- src/test/ui/issues/issue-35570.rs | 3 +- src/test/ui/issues/issue-35570.stderr | 12 ++- src/test/ui/nll/normalization-bounds-error.stderr | 8 +- .../regions-implied-bounds-projection-gap-hr-1.rs | 3 +- ...gions-implied-bounds-projection-gap-hr-1.stderr | 17 +++- .../min_specialization/issue-79224.stderr | 18 ++-- src/test/ui/traits/issue-91594.stderr | 4 +- src/test/ui/wf/wf-foreign-fn-decl-ret.stderr | 4 +- 22 files changed, 251 insertions(+), 172 deletions(-) create mode 100644 compiler/rustc_ty_utils/src/implied_bounds.rs diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index cfc75f673c8..c8230117b93 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -765,6 +765,14 @@ rustc_queries! { desc { |tcx| "processing `{}`", tcx.def_path_str(key.to_def_id()) } } + /// Returns the types assumed to be well formed while "inside" of the given item. + /// + /// Note that we've liberated the late bound regions of function signatures, so + /// this can not be used to check whether these types are well formed. + query assumed_wf_types(key: DefId) -> &'tcx ty::List> { + desc { |tcx| "computing the implied bounds of {}", tcx.def_path_str(key) } + } + /// Computes the signature of the function. query fn_sig(key: DefId) -> ty::PolyFnSig<'tcx> { desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) } diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs new file mode 100644 index 00000000000..a77ea440aaa --- /dev/null +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -0,0 +1,60 @@ +use crate::rustc_middle::ty::DefIdTree; +use rustc_hir::{def::DefKind, def_id::DefId}; +use rustc_middle::ty::{self, Ty, TyCtxt}; + +pub fn provide(providers: &mut ty::query::Providers) { + *providers = ty::query::Providers { assumed_wf_types, ..*providers }; +} + +fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::List> { + match tcx.def_kind(def_id) { + DefKind::Fn => { + let sig = tcx.fn_sig(def_id); + let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig); + liberated_sig.inputs_and_output + } + DefKind::AssocFn => { + let sig = tcx.fn_sig(def_id); + let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig); + let mut assumed_wf_types: Vec<_> = + tcx.assumed_wf_types(tcx.parent(def_id)).as_slice().into(); + assumed_wf_types.extend(liberated_sig.inputs_and_output); + tcx.intern_type_list(&assumed_wf_types) + } + DefKind::Impl => match tcx.impl_trait_ref(def_id) { + Some(trait_ref) => { + let types: Vec<_> = trait_ref.substs.types().collect(); + tcx.intern_type_list(&types) + } + // Only the impl self type + None => tcx.intern_type_list(&[tcx.type_of(def_id)]), + }, + DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)), + DefKind::Mod + | DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::Variant + | DefKind::Trait + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::TraitAlias + | DefKind::TyParam + | DefKind::Const + | DefKind::ConstParam + | DefKind::Static(_) + | DefKind::Ctor(_, _) + | DefKind::Macro(_) + | DefKind::ExternCrate + | DefKind::Use + | DefKind::ForeignMod + | DefKind::AnonConst + | DefKind::InlineConst + | DefKind::OpaqueTy + | DefKind::Field + | DefKind::LifetimeParam + | DefKind::GlobalAsm + | DefKind::Closure + | DefKind::Generator => ty::List::empty(), + } +} diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 09f5c2a11aa..55d82693994 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -21,6 +21,7 @@ use rustc_middle::ty::query::Providers; mod assoc; mod common_traits; mod consts; +mod implied_bounds; pub mod instance; mod needs_drop; pub mod representability; @@ -30,6 +31,7 @@ pub fn provide(providers: &mut Providers) { assoc::provide(providers); common_traits::provide(providers); consts::provide(providers); + implied_bounds::provide(providers); needs_drop::provide(providers); ty::provide(providers); instance::provide(providers); diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index ec8d22e81d1..542794a5e81 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1,6 +1,5 @@ use super::potentially_plural_count; use crate::check::regionck::OutlivesEnvironmentExt; -use crate::check::wfcheck; use crate::errors::LifetimesOrBoundsMismatchOnTrait; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed}; @@ -1445,14 +1444,24 @@ pub fn check_type_bounds<'tcx>( }; debug!(?normalize_param_env); + let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local()); let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id); let rebased_substs = impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs); tcx.infer_ctxt().enter(move |infcx| { let ocx = ObligationCtxt::new(&infcx); + let assumed_wf_types = tcx.assumed_wf_types(impl_ty.def_id); + let mut implied_bounds = FxHashSet::default(); + let cause = ObligationCause::misc(impl_ty_span, impl_ty_hir_id); + for ty in assumed_wf_types { + implied_bounds.insert(ty); + let normalized = ocx.normalize(cause.clone(), param_env, ty); + implied_bounds.insert(normalized); + } + let implied_bounds = implied_bounds; + let mut selcx = traits::SelectionContext::new(&infcx); - let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local()); let normalize_cause = ObligationCause::new( impl_ty_span, impl_ty_hir_id, @@ -1508,15 +1517,6 @@ pub fn check_type_bounds<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. - let implied_bounds = match impl_ty.container { - ty::TraitContainer => FxHashSet::default(), - ty::ImplContainer => wfcheck::impl_implied_bounds( - tcx, - param_env, - container_id.expect_local(), - impl_ty_span, - ), - }; let mut outlives_environment = OutlivesEnvironment::new(param_env); outlives_environment.add_implied_bounds(&infcx, implied_bounds, impl_ty_hir_id); infcx.check_region_obligations_and_report_errors( diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index d0334cd0df7..2ac183b504e 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -10,7 +10,6 @@ use rustc_hir::ItemKind; use rustc_infer::infer::outlives::env::{OutlivesEnvironment, RegionBoundPairs}; use rustc_infer::infer::outlives::obligations::TypeOutlives; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::Normalized; use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst}; use rustc_middle::ty::trait_def::TraitSpecializationKind; @@ -24,8 +23,6 @@ use rustc_span::{Span, DUMMY_SP}; use rustc_trait_selection::autoderef::Autoderef; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; -use rustc_trait_selection::traits::query::normalize::AtExt; -use rustc_trait_selection::traits::query::NoSolution; use rustc_trait_selection::traits::{ self, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc, }; @@ -86,18 +83,29 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( body_def_id: LocalDefId, f: F, ) where - F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>) -> FxHashSet>, + F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>), { let param_env = tcx.param_env(body_def_id); let body_id = tcx.hir().local_def_id_to_hir_id(body_def_id); tcx.infer_ctxt().enter(|ref infcx| { let ocx = ObligationCtxt::new(infcx); + + let assumed_wf_types = tcx.assumed_wf_types(body_def_id); + let mut implied_bounds = FxHashSet::default(); + let cause = ObligationCause::misc(span, body_id); + for ty in assumed_wf_types { + implied_bounds.insert(ty); + let normalized = ocx.normalize(cause.clone(), param_env, ty); + implied_bounds.insert(normalized); + } + let implied_bounds = implied_bounds; + let mut wfcx = WfCheckingCtxt { ocx, span, body_id, param_env }; if !tcx.features().trivial_bounds { wfcx.check_false_global_bounds() } - let wf_tys = f(&mut wfcx); + f(&mut wfcx); let errors = wfcx.select_all_or_error(); if !errors.is_empty() { infcx.report_fulfillment_errors(&errors, None, false); @@ -105,7 +113,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( } let mut outlives_environment = OutlivesEnvironment::new(param_env); - outlives_environment.add_implied_bounds(infcx, wf_tys, body_id); + outlives_environment.add_implied_bounds(infcx, implied_bounds, body_id); infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment); }) } @@ -976,15 +984,9 @@ fn check_associated_item( enter_wf_checking_ctxt(tcx, span, item_id, |wfcx| { let item = tcx.associated_item(item_id); - let (mut implied_bounds, self_ty) = match item.container { - ty::TraitContainer => (FxHashSet::default(), tcx.types.self_param), - ty::ImplContainer => { - let def_id = item.container_id(tcx); - ( - impl_implied_bounds(tcx, wfcx.param_env, def_id.expect_local(), span), - tcx.type_of(def_id), - ) - } + let self_ty = match item.container { + ty::TraitContainer => tcx.types.self_param, + ty::ImplContainer => tcx.type_of(item.container_id(tcx)), }; match item.kind { @@ -1002,7 +1004,6 @@ fn check_associated_item( sig, hir_sig.decl, item.def_id.expect_local(), - &mut implied_bounds, ); check_method_receiver(wfcx, hir_sig, item, self_ty); } @@ -1017,8 +1018,6 @@ fn check_associated_item( } } } - - implied_bounds }) } @@ -1118,9 +1117,6 @@ fn check_type_defn<'tcx, F>( } check_where_clauses(wfcx, item.span, item.def_id); - - // No implied bounds in a struct definition. - FxHashSet::default() }); } @@ -1144,9 +1140,7 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { } enter_wf_checking_ctxt(tcx, item.span, item.def_id, |wfcx| { - check_where_clauses(wfcx, item.span, item.def_id); - - FxHashSet::default() + check_where_clauses(wfcx, item.span, item.def_id) }); // Only check traits, don't check trait aliases @@ -1186,9 +1180,7 @@ fn check_item_fn( ) { enter_wf_checking_ctxt(tcx, span, def_id, |wfcx| { let sig = tcx.fn_sig(def_id); - let mut implied_bounds = FxHashSet::default(); - check_fn_or_method(wfcx, ident.span, sig, decl, def_id, &mut implied_bounds); - implied_bounds + check_fn_or_method(wfcx, ident.span, sig, decl, def_id); }) } @@ -1231,9 +1223,6 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo tcx.require_lang_item(LangItem::Sync, Some(ty_span)), ); } - - // No implied bounds in a const, etc. - FxHashSet::default() }); } @@ -1284,8 +1273,6 @@ fn check_impl<'tcx>( } check_where_clauses(wfcx, item.span, item.def_id); - - impl_implied_bounds(tcx, wfcx.param_env, item.def_id, item.span) }); } @@ -1479,7 +1466,6 @@ fn check_fn_or_method<'tcx>( sig: ty::PolyFnSig<'tcx>, hir_decl: &hir::FnDecl<'_>, def_id: LocalDefId, - implied_bounds: &mut FxHashSet>, ) { let tcx = wfcx.tcx(); let sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig); @@ -1521,15 +1507,8 @@ fn check_fn_or_method<'tcx>( ); } - implied_bounds.extend(sig.inputs()); - wfcx.register_wf_obligation(hir_decl.output.span(), None, sig.output().into()); - // FIXME(#27579) return types should not be implied bounds - implied_bounds.insert(sig.output()); - - debug!(?implied_bounds); - check_where_clauses(wfcx, span, def_id); } @@ -1924,40 +1903,6 @@ impl<'a, 'tcx> WfCheckingCtxt<'a, 'tcx> { } } -pub fn impl_implied_bounds<'tcx>( - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - impl_def_id: LocalDefId, - span: Span, -) -> FxHashSet> { - // We completely ignore any obligations caused by normalizing the types - // we assume to be well formed. Considering that the user of the implied - // bounds will also normalize them, we leave it to them to emit errors - // which should result in better causes and spans. - tcx.infer_ctxt().enter(|infcx| { - let cause = ObligationCause::misc(span, tcx.hir().local_def_id_to_hir_id(impl_def_id)); - match tcx.impl_trait_ref(impl_def_id) { - Some(trait_ref) => { - // Trait impl: take implied bounds from all types that - // appear in the trait reference. - match infcx.at(&cause, param_env).normalize(trait_ref) { - Ok(Normalized { value, obligations: _ }) => value.substs.types().collect(), - Err(NoSolution) => FxHashSet::default(), - } - } - - None => { - // Inherent impl: take implied bounds from the `self` type. - let self_ty = tcx.type_of(impl_def_id); - match infcx.at(&cause, param_env).normalize(self_ty) { - Ok(Normalized { value, obligations: _ }) => FxHashSet::from_iter([value]), - Err(NoSolution) => FxHashSet::default(), - } - } - } - }) -} - fn error_392( tcx: TyCtxt<'_>, span: Span, diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs index 74abb71a18e..cc8453bf1d0 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -66,26 +66,25 @@ //! on traits with methods can. use crate::check::regionck::OutlivesEnvironmentExt; -use crate::check::wfcheck::impl_implied_bounds; use crate::constrained_generic_params as cgp; use crate::errors::SubstsOnOverriddenImpl; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::specialization_graph::Node; +use rustc_infer::traits::ObligationCause; use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{self, TyCtxt, TypeVisitable}; use rustc_span::Span; -use rustc_trait_selection::traits::{self, translate_substs, wf}; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt; +use rustc_trait_selection::traits::{self, translate_substs, wf, ObligationCtxt}; pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) { if let Some(node) = parent_specialization_node(tcx, impl_def_id) { - tcx.infer_ctxt().enter(|infcx| { - check_always_applicable(&infcx, impl_def_id, node); - }); + check_always_applicable(tcx, impl_def_id, node); } } @@ -105,16 +104,14 @@ fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId) -> Opti } /// Check that `impl1` is a sound specialization -fn check_always_applicable(infcx: &InferCtxt<'_, '_>, impl1_def_id: LocalDefId, impl2_node: Node) { - if let Some((impl1_substs, impl2_substs)) = get_impl_substs(infcx, impl1_def_id, impl2_node) { +fn check_always_applicable(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node) { + if let Some((impl1_substs, impl2_substs)) = get_impl_substs(tcx, impl1_def_id, impl2_node) { let impl2_def_id = impl2_node.def_id(); debug!( "check_always_applicable(\nimpl1_def_id={:?},\nimpl2_def_id={:?},\nimpl2_substs={:?}\n)", impl1_def_id, impl2_def_id, impl2_substs ); - let tcx = infcx.tcx; - let parent_substs = if impl2_node.is_from_trait() { impl2_substs.to_vec() } else { @@ -124,7 +121,7 @@ fn check_always_applicable(infcx: &InferCtxt<'_, '_>, impl1_def_id: LocalDefId, let span = tcx.def_span(impl1_def_id); check_static_lifetimes(tcx, &parent_substs, span); check_duplicate_params(tcx, impl1_substs, &parent_substs, span); - check_predicates(infcx, impl1_def_id, impl1_substs, impl2_node, impl2_substs, span); + check_predicates(tcx, impl1_def_id, impl1_substs, impl2_node, impl2_substs, span); } } @@ -139,32 +136,45 @@ fn check_always_applicable(infcx: &InferCtxt<'_, '_>, impl1_def_id: LocalDefId, /// /// Would return `S1 = [C]` and `S2 = [Vec, C]`. fn get_impl_substs<'tcx>( - infcx: &InferCtxt<'_, 'tcx>, + tcx: TyCtxt<'tcx>, impl1_def_id: LocalDefId, impl2_node: Node, ) -> Option<(SubstsRef<'tcx>, SubstsRef<'tcx>)> { - let tcx = infcx.tcx; - let param_env = tcx.param_env(impl1_def_id); + tcx.infer_ctxt().enter(|ref infcx| { + let ocx = ObligationCtxt::new(infcx); + let param_env = tcx.param_env(impl1_def_id); + let impl1_hir_id = tcx.hir().local_def_id_to_hir_id(impl1_def_id); - let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id.to_def_id()); - let impl2_substs = - translate_substs(infcx, param_env, impl1_def_id.to_def_id(), impl1_substs, impl2_node); + let assumed_wf_types = tcx.assumed_wf_types(impl1_def_id); + let mut implied_bounds = FxHashSet::default(); + let cause = ObligationCause::misc(tcx.def_span(impl1_def_id), impl1_hir_id); + for ty in assumed_wf_types { + implied_bounds.insert(ty); + let normalized = ocx.normalize(cause.clone(), param_env, ty); + implied_bounds.insert(normalized); + } + let implied_bounds = implied_bounds; - let mut outlives_env = OutlivesEnvironment::new(param_env); - let implied_bounds = - impl_implied_bounds(infcx.tcx, param_env, impl1_def_id, tcx.def_span(impl1_def_id)); - outlives_env.add_implied_bounds( - infcx, - implied_bounds, - tcx.hir().local_def_id_to_hir_id(impl1_def_id), - ); - infcx.check_region_obligations_and_report_errors(impl1_def_id, &outlives_env); - let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else { - let span = tcx.def_span(impl1_def_id); - tcx.sess.emit_err(SubstsOnOverriddenImpl { span }); - return None; - }; - Some((impl1_substs, impl2_substs)) + let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id.to_def_id()); + let impl2_substs = + translate_substs(infcx, param_env, impl1_def_id.to_def_id(), impl1_substs, impl2_node); + + let errors = ocx.select_all_or_error(); + if !errors.is_empty() { + ocx.infcx.report_fulfillment_errors(&errors, None, false); + return None; + } + + let mut outlives_env = OutlivesEnvironment::new(param_env); + outlives_env.add_implied_bounds(infcx, implied_bounds, impl1_hir_id); + infcx.check_region_obligations_and_report_errors(impl1_def_id, &outlives_env); + let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else { + let span = tcx.def_span(impl1_def_id); + tcx.sess.emit_err(SubstsOnOverriddenImpl { span }); + return None; + }; + Some((impl1_substs, impl2_substs)) + }) } /// Returns a list of all of the unconstrained subst of the given impl. @@ -279,14 +289,13 @@ fn check_static_lifetimes<'tcx>( /// * a well-formed predicate of a type argument of the trait being implemented, /// including the `Self`-type. fn check_predicates<'tcx>( - infcx: &InferCtxt<'_, 'tcx>, + tcx: TyCtxt<'tcx>, impl1_def_id: LocalDefId, impl1_substs: SubstsRef<'tcx>, impl2_node: Node, impl2_substs: SubstsRef<'tcx>, span: Span, ) { - let tcx = infcx.tcx; let instantiated = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs); let impl1_predicates: Vec<_> = traits::elaborate_predicates_with_span( tcx, @@ -343,19 +352,23 @@ fn check_predicates<'tcx>( // Include the well-formed predicates of the type parameters of the impl. for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().substs { - if let Some(obligations) = wf::obligations( - infcx, - tcx.param_env(impl1_def_id), - tcx.hir().local_def_id_to_hir_id(impl1_def_id), - 0, - arg, - span, - ) { + tcx.infer_ctxt().enter(|ref infcx| { + let obligations = wf::obligations( + infcx, + tcx.param_env(impl1_def_id), + tcx.hir().local_def_id_to_hir_id(impl1_def_id), + 0, + arg, + span, + ) + .unwrap(); + + assert!(!obligations.needs_infer()); impl2_predicates.extend( traits::elaborate_obligations(tcx, obligations) .map(|obligation| obligation.predicate), ) - } + }) } impl2_predicates.extend( traits::elaborate_predicates_with_span(tcx, always_applicable_traits) diff --git a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr index 6552c8be780..389cc7beddd 100644 --- a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr +++ b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-for-unimpl-trait.rs:10:40 + --> $DIR/associated-types-for-unimpl-trait.rs:10:5 | LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | help: consider further restricting `Self` | diff --git a/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr b/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr index b2ee1b5e6d0..1feaa612ee6 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `T: Get` is not satisfied - --> $DIR/associated-types-no-suitable-bound.rs:11:21 + --> $DIR/associated-types-no-suitable-bound.rs:11:5 | LL | fn uhoh(foo: ::Value) {} - | ^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T` | help: consider restricting type parameter `T` | diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr index 2e40dbd065d..cc3ed556115 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:40 + --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:5 | LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | help: consider further restricting `Self` | diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr index bd3ee2abd2c..18f2830d8b2 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr @@ -1,14 +1,14 @@ error[E0277]: the trait bound `(T, U): Get` is not satisfied - --> $DIR/associated-types-no-suitable-supertrait.rs:22:40 + --> $DIR/associated-types-no-suitable-supertrait.rs:22:5 | LL | fn uhoh(&self, foo: U, bar: <(T, U) as Get>::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)` error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-no-suitable-supertrait.rs:17:40 + --> $DIR/associated-types-no-suitable-supertrait.rs:17:5 | LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | help: consider further restricting `Self` | diff --git a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr index 2e67c21940f..66d59bccdbb 100644 --- a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr +++ b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:40 + --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:5 | LL | fn okay(&self, foo: U, bar: ::Value); - | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | help: consider further restricting `Self` | diff --git a/src/test/ui/associated-types/issue-59324.stderr b/src/test/ui/associated-types/issue-59324.stderr index dd5ec7175b5..62cf1f37a77 100644 --- a/src/test/ui/associated-types/issue-59324.stderr +++ b/src/test/ui/associated-types/issue-59324.stderr @@ -45,16 +45,20 @@ LL | pub trait ThriftService: | +++++ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/issue-59324.rs:23:29 + --> $DIR/issue-59324.rs:23:1 | LL | fn with_factory(factory: dyn ThriftService<()>) {} - | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` error[E0277]: the trait bound `Bug: Foo` is not satisfied - --> $DIR/issue-59324.rs:16:8 + --> $DIR/issue-59324.rs:16:5 | -LL | fn get_service( - | ^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug` +LL | / fn get_service( +LL | | +LL | | +LL | | &self, +LL | | ) -> Self::AssocType; + | |_________________________^ the trait `Foo` is not implemented for `Bug` | help: consider further restricting this bound | diff --git a/src/test/ui/issues/issue-18611.stderr b/src/test/ui/issues/issue-18611.stderr index bd18d46223e..22c3470b61e 100644 --- a/src/test/ui/issues/issue-18611.stderr +++ b/src/test/ui/issues/issue-18611.stderr @@ -1,8 +1,10 @@ error[E0277]: the trait bound `isize: HasState` is not satisfied - --> $DIR/issue-18611.rs:1:18 + --> $DIR/issue-18611.rs:1:1 | -LL | fn add_state(op: ::State) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasState` is not implemented for `isize` +LL | / fn add_state(op: ::State) { +LL | | +LL | | } + | |_^ the trait `HasState` is not implemented for `isize` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20831-debruijn.stderr b/src/test/ui/issues/issue-20831-debruijn.stderr index 57f9575bdbd..ef62dece836 100644 --- a/src/test/ui/issues/issue-20831-debruijn.stderr +++ b/src/test/ui/issues/issue-20831-debruijn.stderr @@ -1,8 +1,14 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/issue-20831-debruijn.rs:28:8 + --> $DIR/issue-20831-debruijn.rs:28:5 | -LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { - | ^^^^^^^^^ +LL | / fn subscribe(&mut self, t : Box::Output> + 'a>) { +LL | | // Not obvious, but there is an implicit lifetime here -------^ +LL | | +LL | | // +... | +LL | | self.sub = t; +LL | | } + | |_____^ | note: first, the lifetime cannot outlive the anonymous lifetime defined here... --> $DIR/issue-20831-debruijn.rs:28:58 @@ -15,10 +21,16 @@ note: ...but the lifetime must also be valid for the lifetime `'a` as defined he LL | impl<'a> Publisher<'a> for MyStruct<'a> { | ^^ note: ...so that the types are compatible - --> $DIR/issue-20831-debruijn.rs:28:8 + --> $DIR/issue-20831-debruijn.rs:28:5 | -LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { - | ^^^^^^^^^ +LL | / fn subscribe(&mut self, t : Box::Output> + 'a>) { +LL | | // Not obvious, but there is an implicit lifetime here -------^ +LL | | +LL | | // +... | +LL | | self.sub = t; +LL | | } + | |_____^ = note: expected ` as Publisher<'_>>` found ` as Publisher<'_>>` diff --git a/src/test/ui/issues/issue-35570.rs b/src/test/ui/issues/issue-35570.rs index 42cef9a47f2..a2b0222d4f3 100644 --- a/src/test/ui/issues/issue-35570.rs +++ b/src/test/ui/issues/issue-35570.rs @@ -6,7 +6,8 @@ trait Trait2<'a> { } fn _ice(param: Box Trait1<<() as Trait2<'a>>::Ty>>) { -//~^ the trait bound `for<'a> (): Trait2<'a>` is not satisfied + //~^ ERROR the trait bound `for<'a> (): Trait2<'a>` is not satisfied + //~| ERROR the trait bound `for<'a> (): Trait2<'a>` is not satisfied let _e: (usize, usize) = unsafe{mem::transmute(param)}; } diff --git a/src/test/ui/issues/issue-35570.stderr b/src/test/ui/issues/issue-35570.stderr index 2697d46bdb2..ebc40f6786f 100644 --- a/src/test/ui/issues/issue-35570.stderr +++ b/src/test/ui/issues/issue-35570.stderr @@ -1,9 +1,19 @@ +error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied + --> $DIR/issue-35570.rs:8:1 + | +LL | / fn _ice(param: Box Trait1<<() as Trait2<'a>>::Ty>>) { +LL | | +LL | | +LL | | let _e: (usize, usize) = unsafe{mem::transmute(param)}; +LL | | } + | |_^ the trait `for<'a> Trait2<'a>` is not implemented for `()` + error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied --> $DIR/issue-35570.rs:8:40 | LL | fn _ice(param: Box Trait1<<() as Trait2<'a>>::Ty>>) { | ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait2<'a>` is not implemented for `()` -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/nll/normalization-bounds-error.stderr b/src/test/ui/nll/normalization-bounds-error.stderr index 6da3d5d9692..6abe53127c3 100644 --- a/src/test/ui/nll/normalization-bounds-error.stderr +++ b/src/test/ui/nll/normalization-bounds-error.stderr @@ -1,8 +1,8 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'d` due to conflicting requirements - --> $DIR/normalization-bounds-error.rs:12:4 + --> $DIR/normalization-bounds-error.rs:12:1 | LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} - | ^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first, the lifetime cannot outlive the lifetime `'d` as defined here... --> $DIR/normalization-bounds-error.rs:12:14 @@ -15,10 +15,10 @@ note: ...but the lifetime must also be valid for the lifetime `'a` as defined he LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} | ^^ note: ...so that the types are compatible - --> $DIR/normalization-bounds-error.rs:12:4 + --> $DIR/normalization-bounds-error.rs:12:1 | LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} - | ^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: expected `Visitor<'d>` found `Visitor<'_>` diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs index c1dab6086ef..1106352037a 100644 --- a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs +++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs @@ -19,7 +19,8 @@ trait Trait2<'a, 'b> { // since for it to be WF, we would need to know that `'y: 'x`, but we // do not infer that. fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< >::Foo >) - //~^ the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied + //~^ ERROR the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied + //~| ERROR the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied { } diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr index 6844e866532..66f592c34dd 100644 --- a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr +++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr @@ -1,3 +1,18 @@ +error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied + --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:1 + | +LL | / fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< >::Foo >) +LL | | +LL | | +LL | | { +LL | | } + | |_^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< >::Foo >) + | ++++++++++++++++++++++++ + error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:49 | @@ -9,6 +24,6 @@ help: consider restricting type parameter `T` LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< >::Foo >) | ++++++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/specialization/min_specialization/issue-79224.stderr b/src/test/ui/specialization/min_specialization/issue-79224.stderr index cfb9007c7a2..b395d93f097 100644 --- a/src/test/ui/specialization/min_specialization/issue-79224.stderr +++ b/src/test/ui/specialization/min_specialization/issue-79224.stderr @@ -1,8 +1,12 @@ error[E0277]: the trait bound `B: Clone` is not satisfied - --> $DIR/issue-79224.rs:18:17 + --> $DIR/issue-79224.rs:18:1 | -LL | impl Display for Cow<'_, B> { - | ^^^^^^^ the trait `Clone` is not implemented for `B` +LL | / impl Display for Cow<'_, B> { +LL | | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +LL | | write!(f, "foo") +LL | | } +LL | | } + | |_^ the trait `Clone` is not implemented for `B` | = note: required because of the requirements on the impl of `ToOwned` for `B` help: consider further restricting this bound @@ -11,10 +15,12 @@ LL | impl Display for Cow<'_, B> { | +++++++++++++++++++ error[E0277]: the trait bound `B: Clone` is not satisfied - --> $DIR/issue-79224.rs:19:12 + --> $DIR/issue-79224.rs:19:5 | -LL | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - | ^^^^^ the trait `Clone` is not implemented for `B` +LL | / fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +LL | | write!(f, "foo") +LL | | } + | |_____^ the trait `Clone` is not implemented for `B` | = note: required because of the requirements on the impl of `ToOwned` for `B` help: consider further restricting this bound diff --git a/src/test/ui/traits/issue-91594.stderr b/src/test/ui/traits/issue-91594.stderr index f2b3de13beb..b9f1d8c6a2e 100644 --- a/src/test/ui/traits/issue-91594.stderr +++ b/src/test/ui/traits/issue-91594.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `Foo: HasComponent<()>` is not satisfied - --> $DIR/issue-91594.rs:10:6 + --> $DIR/issue-91594.rs:10:1 | LL | impl HasComponent<>::Interface> for Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo` | = help: the trait `HasComponent<>::Interface>` is implemented for `Foo` note: required because of the requirements on the impl of `Component` for `Foo` diff --git a/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr b/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr index b03023b5fd1..78312a09105 100644 --- a/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr +++ b/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/wf-foreign-fn-decl-ret.rs:11:25 + --> $DIR/wf-foreign-fn-decl-ret.rs:11:5 | LL | pub fn lint_me() -> <() as Foo>::Assoc; - | ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` error[E0277]: the trait bound `u32: Unsatisfied` is not satisfied --> $DIR/wf-foreign-fn-decl-ret.rs:14:32 -- cgit 1.4.1-3-g733a5 From f57e6fa453341a8012f0cdf951e0cd10f5e58ab0 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 17 Aug 2022 12:54:12 +0200 Subject: `compare_predicate_entailment` move comment --- compiler/rustc_typeck/src/check/compare_method.rs | 129 +++++++++++----------- 1 file changed, 66 insertions(+), 63 deletions(-) diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 542794a5e81..0716b3bc670 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -70,6 +70,72 @@ pub(crate) fn compare_impl_method<'tcx>( } } +/// This function is best explained by example. Consider a trait: +/// +/// trait Trait<'t, T> { +/// // `trait_m` +/// fn method<'a, M>(t: &'t T, m: &'a M) -> Self; +/// } +/// +/// And an impl: +/// +/// impl<'i, 'j, U> Trait<'j, &'i U> for Foo { +/// // `impl_m` +/// fn method<'b, N>(t: &'j &'i U, m: &'b N) -> Foo; +/// } +/// +/// We wish to decide if those two method types are compatible. +/// For this we have to show that, assuming the bounds of the impl hold, the +/// bounds of `trait_m` imply the bounds of `impl_m`. +/// +/// We start out with `trait_to_impl_substs`, that maps the trait +/// type parameters to impl type parameters. This is taken from the +/// impl trait reference: +/// +/// trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo} +/// +/// We create a mapping `dummy_substs` that maps from the impl type +/// parameters to fresh types and regions. For type parameters, +/// this is the identity transform, but we could as well use any +/// placeholder types. For regions, we convert from bound to free +/// regions (Note: but only early-bound regions, i.e., those +/// declared on the impl or used in type parameter bounds). +/// +/// impl_to_placeholder_substs = {'i => 'i0, U => U0, N => N0 } +/// +/// Now we can apply `placeholder_substs` to the type of the impl method +/// to yield a new function type in terms of our fresh, placeholder +/// types: +/// +/// <'b> fn(t: &'i0 U0, m: &'b) -> Foo +/// +/// We now want to extract and substitute the type of the *trait* +/// method and compare it. To do so, we must create a compound +/// substitution by combining `trait_to_impl_substs` and +/// `impl_to_placeholder_substs`, and also adding a mapping for the method +/// type parameters. We extend the mapping to also include +/// the method parameters. +/// +/// trait_to_placeholder_substs = { T => &'i0 U0, Self => Foo, M => N0 } +/// +/// Applying this to the trait method type yields: +/// +/// <'a> fn(t: &'i0 U0, m: &'a) -> Foo +/// +/// This type is also the same but the name of the bound region (`'a` +/// vs `'b`). However, the normal subtyping rules on fn types handle +/// this kind of equivalency just fine. +/// +/// We now use these substitutions to ensure that all declared bounds are +/// satisfied by the implementation's method. +/// +/// We do this by creating a parameter environment which contains a +/// substitution corresponding to `impl_to_placeholder_substs`. We then build +/// `trait_to_placeholder_substs` and use it to convert the predicates contained +/// in the `trait_m` generics to the placeholder form. +/// +/// Finally we register each of these predicates as an obligation and check that +/// they hold. fn compare_predicate_entailment<'tcx>( tcx: TyCtxt<'tcx>, impl_m: &ty::AssocItem, @@ -96,69 +162,6 @@ fn compare_predicate_entailment<'tcx>( }, ); - // This code is best explained by example. Consider a trait: - // - // trait Trait<'t, T> { - // fn method<'a, M>(t: &'t T, m: &'a M) -> Self; - // } - // - // And an impl: - // - // impl<'i, 'j, U> Trait<'j, &'i U> for Foo { - // fn method<'b, N>(t: &'j &'i U, m: &'b N) -> Foo; - // } - // - // We wish to decide if those two method types are compatible. - // - // We start out with trait_to_impl_substs, that maps the trait - // type parameters to impl type parameters. This is taken from the - // impl trait reference: - // - // trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo} - // - // We create a mapping `dummy_substs` that maps from the impl type - // parameters to fresh types and regions. For type parameters, - // this is the identity transform, but we could as well use any - // placeholder types. For regions, we convert from bound to free - // regions (Note: but only early-bound regions, i.e., those - // declared on the impl or used in type parameter bounds). - // - // impl_to_placeholder_substs = {'i => 'i0, U => U0, N => N0 } - // - // Now we can apply placeholder_substs to the type of the impl method - // to yield a new function type in terms of our fresh, placeholder - // types: - // - // <'b> fn(t: &'i0 U0, m: &'b) -> Foo - // - // We now want to extract and substitute the type of the *trait* - // method and compare it. To do so, we must create a compound - // substitution by combining trait_to_impl_substs and - // impl_to_placeholder_substs, and also adding a mapping for the method - // type parameters. We extend the mapping to also include - // the method parameters. - // - // trait_to_placeholder_substs = { T => &'i0 U0, Self => Foo, M => N0 } - // - // Applying this to the trait method type yields: - // - // <'a> fn(t: &'i0 U0, m: &'a) -> Foo - // - // This type is also the same but the name of the bound region ('a - // vs 'b). However, the normal subtyping rules on fn types handle - // this kind of equivalency just fine. - // - // We now use these substitutions to ensure that all declared bounds are - // satisfied by the implementation's method. - // - // We do this by creating a parameter environment which contains a - // substitution corresponding to impl_to_placeholder_substs. We then build - // trait_to_placeholder_substs and use it to convert the predicates contained - // in the trait_m.generics to the placeholder form. - // - // Finally we register each of these predicates as an obligation in - // a fresh FulfillmentCtxt, and invoke select_all_or_error. - // Create mapping from impl to placeholder. let impl_to_placeholder_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id); -- cgit 1.4.1-3-g733a5 From e9e46c95ce60469f596b8188c439dc278dff6bc4 Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Wed, 17 Aug 2022 06:07:33 -0500 Subject: Don't treat stashed warnings as errors --- compiler/rustc_errors/src/lib.rs | 74 +++++++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 395bf5aad01..fe2afdf5a20 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -625,19 +625,13 @@ impl Handler { /// Stash a given diagnostic with the given `Span` and `StashKey` as the key for later stealing. pub fn stash_diagnostic(&self, span: Span, key: StashKey, diag: Diagnostic) { let mut inner = self.inner.borrow_mut(); - // FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic - // if/when we have a more robust macro-friendly replacement for `(span, key)` as a key. - // See the PR for a discussion. - inner.stashed_diagnostics.insert((span, key), diag); + inner.stash((span, key), diag); } /// Steal a previously stashed diagnostic with the given `Span` and `StashKey` as the key. pub fn steal_diagnostic(&self, span: Span, key: StashKey) -> Option> { - self.inner - .borrow_mut() - .stashed_diagnostics - .remove(&(span, key)) - .map(|diag| DiagnosticBuilder::new_diagnostic(self, diag)) + let mut inner = self.inner.borrow_mut(); + inner.steal((span, key)).map(|diag| DiagnosticBuilder::new_diagnostic(self, diag)) } /// Emit all stashed diagnostics. @@ -1105,13 +1099,31 @@ impl HandlerInner { /// Emit all stashed diagnostics. fn emit_stashed_diagnostics(&mut self) -> Option { + let has_errors = self.has_errors(); let diags = self.stashed_diagnostics.drain(..).map(|x| x.1).collect::>(); let mut reported = None; for mut diag in diags { + // Decrement the count tracking the stash; emitting will increment it. if diag.is_error() { - reported = Some(ErrorGuaranteed(())); + if matches!(diag.level, Level::Error { lint: true }) { + self.lint_err_count -= 1; + } else { + self.err_count -= 1; + } + } else { + if diag.is_force_warn() { + self.warn_count -= 1; + } else { + // Unless they're forced, don't flush stashed warnings when + // there are errors, to avoid causing warning overload. The + // stash would've been stolen already if it were important. + if has_errors { + continue; + } + } } - self.emit_diagnostic(&mut diag); + let reported_this = self.emit_diagnostic(&mut diag); + reported = reported.or(reported_this); } reported } @@ -1301,9 +1313,47 @@ impl HandlerInner { } } + fn stash(&mut self, key: (Span, StashKey), diagnostic: Diagnostic) { + // Track the diagnostic for counts, but don't panic-if-treat-err-as-bug + // yet; that happens when we actually emit the diagnostic. + if diagnostic.is_error() { + if matches!(diagnostic.level, Level::Error { lint: true }) { + self.lint_err_count += 1; + } else { + self.err_count += 1; + } + } else { + // Warnings are only automatically flushed if they're forced. + if diagnostic.is_force_warn() { + self.warn_count += 1; + } + } + + // FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic + // if/when we have a more robust macro-friendly replacement for `(span, key)` as a key. + // See the PR for a discussion. + self.stashed_diagnostics.insert(key, diagnostic); + } + + fn steal(&mut self, key: (Span, StashKey)) -> Option { + let diagnostic = self.stashed_diagnostics.remove(&key)?; + if diagnostic.is_error() { + if matches!(diagnostic.level, Level::Error { lint: true }) { + self.lint_err_count -= 1; + } else { + self.err_count -= 1; + } + } else { + if diagnostic.is_force_warn() { + self.warn_count -= 1; + } + } + Some(diagnostic) + } + #[inline] fn err_count(&self) -> usize { - self.err_count + self.stashed_diagnostics.len() + self.err_count } fn has_errors(&self) -> bool { -- cgit 1.4.1-3-g733a5 From 767239f7403a3808e534da02ca388632eac2bc18 Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Wed, 17 Aug 2022 06:52:47 -0500 Subject: Reenable early feature-gates as future-compat warnings --- compiler/rustc_ast_passes/src/feature_gate.rs | 58 +++++++++++++--------- compiler/rustc_errors/src/lib.rs | 1 + compiler/rustc_lint_defs/src/builtin.rs | 51 +++++++++++++++++++ compiler/rustc_session/src/parse.rs | 55 ++++++++++++++++++-- src/test/ui/macros/stringify.rs | 7 +++ .../ui/or-patterns/or-patterns-syntactic-pass.rs | 16 +++--- .../or-patterns/or-patterns-syntactic-pass.stderr | 13 +++++ ...nstraints-before-generic-args-syntactic-pass.rs | 4 ++ ...aints-before-generic-args-syntactic-pass.stderr | 24 +++++++++ src/test/ui/pattern/rest-pat-syntactic.rs | 5 +- src/test/ui/pattern/rest-pat-syntactic.stderr | 24 +++++++++ 11 files changed, 224 insertions(+), 34 deletions(-) create mode 100644 src/test/ui/or-patterns/or-patterns-syntactic-pass.stderr create mode 100644 src/test/ui/parser/constraints-before-generic-args-syntactic-pass.stderr create mode 100644 src/test/ui/pattern/rest-pat-syntactic.stderr diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 97eee56f948..68fca081018 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -2,10 +2,10 @@ use rustc_ast as ast; use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use rustc_ast::{AssocConstraint, AssocConstraintKind, NodeId}; use rustc_ast::{PatKind, RangeEnd, VariantData}; -use rustc_errors::{struct_span_err, Applicability}; +use rustc_errors::{struct_span_err, Applicability, StashKey}; +use rustc_feature::Features; use rustc_feature::{AttributeGate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; -use rustc_feature::{Features, GateIssue}; -use rustc_session::parse::{feature_err, feature_err_issue}; +use rustc_session::parse::{feature_err, feature_warn}; use rustc_session::Session; use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; @@ -20,9 +20,7 @@ macro_rules! gate_feature_fn { let has_feature: bool = has_feature(visitor.features); debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature); if !has_feature && !span.allows_unstable($name) { - feature_err_issue(&visitor.sess.parse_sess, name, span, GateIssue::Language, explain) - .help(help) - .emit(); + feature_err(&visitor.sess.parse_sess, name, span, explain).help(help).emit(); } }}; ($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{ @@ -31,8 +29,19 @@ macro_rules! gate_feature_fn { let has_feature: bool = has_feature(visitor.features); debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature); if !has_feature && !span.allows_unstable($name) { - feature_err_issue(&visitor.sess.parse_sess, name, span, GateIssue::Language, explain) - .emit(); + feature_err(&visitor.sess.parse_sess, name, span, explain).emit(); + } + }}; + (future_incompatible; $visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{ + let (visitor, has_feature, span, name, explain) = + (&*$visitor, $has_feature, $span, $name, $explain); + let has_feature: bool = has_feature(visitor.features); + debug!( + "gate_feature(feature = {:?}, span = {:?}); has? {} (future_incompatible)", + name, span, has_feature + ); + if !has_feature && !span.allows_unstable($name) { + feature_warn(&visitor.sess.parse_sess, name, span, explain); } }}; } @@ -44,6 +53,9 @@ macro_rules! gate_feature_post { ($visitor: expr, $feature: ident, $span: expr, $explain: expr) => { gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain) }; + (future_incompatible; $visitor: expr, $feature: ident, $span: expr, $explain: expr) => { + gate_feature_fn!(future_incompatible; $visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain) + }; } pub fn check_attribute(attr: &ast::Attribute, sess: &Session, features: &Features) { @@ -588,11 +600,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { { // When we encounter a statement of the form `foo: Ty = val;`, this will emit a type // ascription error, but the likely intention was to write a `let` statement. (#78907). - feature_err_issue( + feature_err( &self.sess.parse_sess, sym::type_ascription, lhs.span, - GateIssue::Language, "type ascription is experimental", ).span_suggestion_verbose( lhs.span.shrink_to_lo(), @@ -615,15 +626,22 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ); } ast::ExprKind::Type(..) => { - // To avoid noise about type ascription in common syntax errors, only emit if it - // is the *only* error. if self.sess.parse_sess.span_diagnostic.err_count() == 0 { + // To avoid noise about type ascription in common syntax errors, + // only emit if it is the *only* error. gate_feature_post!( &self, type_ascription, e.span, "type ascription is experimental" ); + } else { + // And if it isn't, cancel the early-pass warning. + self.sess + .parse_sess + .span_diagnostic + .steal_diagnostic(e.span, StashKey::EarlySyntaxWarning) + .map(|err| err.cancel()); } } ast::ExprKind::TryBlock(_) => { @@ -789,14 +807,12 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { // All uses of `gate_all!` below this point were added in #65742, // and subsequently disabled (with the non-early gating readded). + // We emit an early future-incompatible warning for these. + // New syntax gates should go above here to get a hard error gate. macro_rules! gate_all { ($gate:ident, $msg:literal) => { - // FIXME(eddyb) do something more useful than always - // disabling these uses of early feature-gatings. - if false { - for span in spans.get(&sym::$gate).unwrap_or(&vec![]) { - gate_feature_post!(&visitor, $gate, *span, $msg); - } + for span in spans.get(&sym::$gate).unwrap_or(&vec![]) { + gate_feature_post!(future_incompatible; &visitor, $gate, *span, $msg); } }; } @@ -809,11 +825,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { gate_all!(try_blocks, "`try` blocks are unstable"); gate_all!(label_break_value, "labels on blocks are unstable"); gate_all!(box_syntax, "box expression syntax is experimental; you can call `Box::new` instead"); - // To avoid noise about type ascription in common syntax errors, - // only emit if it is the *only* error. (Also check it last.) - if sess.parse_sess.span_diagnostic.err_count() == 0 { - gate_all!(type_ascription, "type ascription is experimental"); - } + gate_all!(type_ascription, "type ascription is experimental"); visit::walk_crate(&mut visitor, krate); } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index fe2afdf5a20..43b8288d8b6 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -458,6 +458,7 @@ struct HandlerInner { pub enum StashKey { ItemNoType, UnderscoreForArrayLengths, + EarlySyntaxWarning, } fn default_track_diagnostic(_: &Diagnostic) {} diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index f00165cd3b3..95e34da734d 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3212,6 +3212,56 @@ declare_lint! { }; } +declare_lint! { + /// The `unstable_syntax_pre_expansion` lint detects the use of unstable + /// syntax that is discarded during attribute expansion. + /// + /// ### Example + /// + /// ```rust + /// #[cfg(FALSE)] + /// macro foo() {} + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// The input to active attributes such as `#[cfg]` or procedural macro + /// attributes is required to be valid syntax. Previously, the compiler only + /// gated the use of unstable syntax features after resolving `#[cfg]` gates + /// and expanding procedural macros. + /// + /// To avoid relying on unstable syntax, move the use of unstable syntax + /// into a position where the compiler does not parse the syntax, such as a + /// functionlike macro. + /// + /// ```rust + /// # #![deny(unstable_syntax_pre_expansion)] + /// + /// macro_rules! identity { + /// ( $($tokens:tt)* ) => { $($tokens)* } + /// } + /// + /// #[cfg(FALSE)] + /// identity! { + /// macro foo() {} + /// } + /// ``` + /// + /// This is a [future-incompatible] lint to transition this + /// to a hard error in the future. See [issue #65860] for more details. + /// + /// [issue #65860]: https://github.com/rust-lang/rust/issues/65860 + /// [future-incompatible]: ../index.md#future-incompatible-lints + pub UNSTABLE_SYNTAX_PRE_EXPANSION, + Warn, + "unstable syntax can change at any point in the future, causing a hard error!", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #65860 ", + }; +} + declare_lint_pass! { /// Does nothing as a lint pass, but registers some `Lint`s /// that are used by other parts of the compiler. @@ -3280,6 +3330,7 @@ declare_lint_pass! { POINTER_STRUCTURAL_MATCH, NONTRIVIAL_STRUCTURAL_MATCH, SOFT_UNSTABLE, + UNSTABLE_SYNTAX_PRE_EXPANSION, INLINE_NO_SANITIZE, BAD_ASM_STYLE, ASM_SUB_REGISTER, diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index f31d52147b4..9f0886cb208 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -2,15 +2,17 @@ //! It also serves as an input to the parser itself. use crate::config::CheckCfg; -use crate::lint::{BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId}; +use crate::lint::{ + builtin::UNSTABLE_SYNTAX_PRE_EXPANSION, BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId, +}; use crate::SessionDiagnostic; use rustc_ast::node_id::NodeId; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{Lock, Lrc}; use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler}; use rustc_errors::{ - error_code, fallback_fluent_bundle, Applicability, Diagnostic, DiagnosticBuilder, - DiagnosticMessage, ErrorGuaranteed, MultiSpan, + error_code, fallback_fluent_bundle, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, + DiagnosticMessage, ErrorGuaranteed, MultiSpan, StashKey, }; use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures}; use rustc_span::edition::Edition; @@ -101,11 +103,58 @@ pub fn feature_err_issue<'a>( issue: GateIssue, explain: &str, ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + let span = span.into(); + + // Cancel an earlier warning for this same error, if it exists. + if let Some(span) = span.primary_span() { + sess.span_diagnostic + .steal_diagnostic(span, StashKey::EarlySyntaxWarning) + .map(|err| err.cancel()); + } + let mut err = sess.span_diagnostic.struct_span_err_with_code(span, explain, error_code!(E0658)); add_feature_diagnostics_for_issue(&mut err, sess, feature, issue); err } +/// Construct a future incompatibility diagnostic for a feature gate. +/// +/// This diagnostic is only a warning and *does not cause compilation to fail*. +pub fn feature_warn<'a>(sess: &'a ParseSess, feature: Symbol, span: Span, explain: &str) { + feature_warn_issue(sess, feature, span, GateIssue::Language, explain); +} + +/// Construct a future incompatibility diagnostic for a feature gate. +/// +/// This diagnostic is only a warning and *does not cause compilation to fail*. +/// +/// This variant allows you to control whether it is a library or language feature. +/// Almost always, you want to use this for a language feature. If so, prefer `feature_warn`. +pub fn feature_warn_issue<'a>( + sess: &'a ParseSess, + feature: Symbol, + span: Span, + issue: GateIssue, + explain: &str, +) { + let mut err = sess.span_diagnostic.struct_span_warn(span, explain); + add_feature_diagnostics_for_issue(&mut err, sess, feature, issue); + + // Decorate this as a future-incompatibility lint as in rustc_middle::lint::struct_lint_level + let lint = UNSTABLE_SYNTAX_PRE_EXPANSION; + let future_incompatible = lint.future_incompatible.as_ref().unwrap(); + err.code(DiagnosticId::Lint { + name: lint.name_lower(), + has_future_breakage: false, + is_force_warn: false, + }); + err.warn(lint.desc); + err.note(format!("for more information, see {}", future_incompatible.reference)); + + // A later feature_err call can steal and cancel this warning. + err.stash(span, StashKey::EarlySyntaxWarning); +} + /// Adds the diagnostics for a feature to an existing error. pub fn add_feature_diagnostics<'a>(err: &mut Diagnostic, sess: &'a ParseSess, feature: Symbol) { add_feature_diagnostics_for_issue(err, sess, feature, GateIssue::Language); diff --git a/src/test/ui/macros/stringify.rs b/src/test/ui/macros/stringify.rs index 8e71ed7c112..082c1abb8f2 100644 --- a/src/test/ui/macros/stringify.rs +++ b/src/test/ui/macros/stringify.rs @@ -3,11 +3,18 @@ // compile-flags: --test #![feature(async_closure)] +#![feature(box_patterns)] +#![feature(box_syntax)] #![feature(const_trait_impl)] +#![feature(decl_macro)] #![feature(generators)] #![feature(half_open_range_patterns)] +#![feature(label_break_value)] #![feature(more_qualified_paths)] #![feature(raw_ref_op)] +#![feature(trait_alias)] +#![feature(try_blocks)] +#![feature(type_ascription)] #![deny(unused_macros)] macro_rules! stringify_block { diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs b/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs index 6f9a631b092..dda5c0bb59d 100644 --- a/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs +++ b/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs @@ -7,7 +7,7 @@ fn main() {} // Test the `pat` macro fragment parser: macro_rules! accept_pat { - ($p:pat) => {} + ($p:pat) => {}; } accept_pat!((p | q)); @@ -21,28 +21,28 @@ accept_pat!([p | q]); #[cfg(FALSE)] fn or_patterns() { // Top level of `let`: - let (| A | B); + let (A | B); let (A | B); let (A | B): u8; let (A | B) = 0; let (A | B): u8 = 0; // Top level of `for`: - for | A | B in 0 {} + for A | B in 0 {} for A | B in 0 {} // Top level of `while`: - while let | A | B = 0 {} + while let A | B = 0 {} while let A | B = 0 {} // Top level of `if`: - if let | A | B = 0 {} + if let A | B = 0 {} if let A | B = 0 {} // Top level of `match` arms: match 0 { - | A | B => {}, - A | B => {}, + A | B => {} + A | B => {} } // Functions: @@ -68,6 +68,8 @@ fn or_patterns() { // These bind as `(prefix p) | q` as opposed to `prefix (p | q)`: let (box 0 | 1); // Unstable; we *can* change the precedence if we want. + //~^ WARN box pattern syntax is experimental + //~| WARN unstable syntax let (&0 | 1); let (&mut 0 | 1); let (x @ 0 | 1); diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-pass.stderr b/src/test/ui/or-patterns/or-patterns-syntactic-pass.stderr new file mode 100644 index 00000000000..c43fe192a73 --- /dev/null +++ b/src/test/ui/or-patterns/or-patterns-syntactic-pass.stderr @@ -0,0 +1,13 @@ +warning: box pattern syntax is experimental + --> $DIR/or-patterns-syntactic-pass.rs:70:10 + | +LL | let (box 0 | 1); // Unstable; we *can* change the precedence if we want. + | ^^^^^ + | + = note: see issue #29641 for more information + = help: add `#![feature(box_patterns)]` to the crate attributes to enable + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: 1 warning emitted + diff --git a/src/test/ui/parser/constraints-before-generic-args-syntactic-pass.rs b/src/test/ui/parser/constraints-before-generic-args-syntactic-pass.rs index afbd13e6fd9..d8346653c25 100644 --- a/src/test/ui/parser/constraints-before-generic-args-syntactic-pass.rs +++ b/src/test/ui/parser/constraints-before-generic-args-syntactic-pass.rs @@ -3,7 +3,11 @@ #[cfg(FALSE)] fn syntax() { foo::(); + //~^ WARN associated type bounds are unstable + //~| WARN unstable syntax foo::(); + //~^ WARN associated type bounds are unstable + //~| WARN unstable syntax } fn main() {} diff --git a/src/test/ui/parser/constraints-before-generic-args-syntactic-pass.stderr b/src/test/ui/parser/constraints-before-generic-args-syntactic-pass.stderr new file mode 100644 index 00000000000..7e843c7f4d0 --- /dev/null +++ b/src/test/ui/parser/constraints-before-generic-args-syntactic-pass.stderr @@ -0,0 +1,24 @@ +warning: associated type bounds are unstable + --> $DIR/constraints-before-generic-args-syntactic-pass.rs:5:19 + | +LL | foo::(); + | ^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: associated type bounds are unstable + --> $DIR/constraints-before-generic-args-syntactic-pass.rs:8:23 + | +LL | foo::(); + | ^^^^^^ + | + = note: see issue #52662 for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: 2 warnings emitted + diff --git a/src/test/ui/pattern/rest-pat-syntactic.rs b/src/test/ui/pattern/rest-pat-syntactic.rs index 9656a0b5de9..4da5a2db767 100644 --- a/src/test/ui/pattern/rest-pat-syntactic.rs +++ b/src/test/ui/pattern/rest-pat-syntactic.rs @@ -19,6 +19,8 @@ fn rest_patterns() { // Box patterns: let box ..; + //~^ WARN box pattern syntax is experimental + //~| WARN unstable syntax // In or-patterns: match x { @@ -57,7 +59,7 @@ fn rest_patterns() { .. | [ ( - box .., + box .., //~ WARN box pattern syntax is experimental &(..), &mut .., x @ .. @@ -67,4 +69,5 @@ fn rest_patterns() { ref mut x @ .. => {} } + //~| WARN unstable syntax } diff --git a/src/test/ui/pattern/rest-pat-syntactic.stderr b/src/test/ui/pattern/rest-pat-syntactic.stderr new file mode 100644 index 00000000000..37019b7d5ba --- /dev/null +++ b/src/test/ui/pattern/rest-pat-syntactic.stderr @@ -0,0 +1,24 @@ +warning: box pattern syntax is experimental + --> $DIR/rest-pat-syntactic.rs:21:9 + | +LL | let box ..; + | ^^^^^^ + | + = note: see issue #29641 for more information + = help: add `#![feature(box_patterns)]` to the crate attributes to enable + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: box pattern syntax is experimental + --> $DIR/rest-pat-syntactic.rs:62:17 + | +LL | box .., + | ^^^^^^ + | + = note: see issue #29641 for more information + = help: add `#![feature(box_patterns)]` to the crate attributes to enable + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: 2 warnings emitted + -- cgit 1.4.1-3-g733a5 From 944c6b6d760d392552fc60ec4e3ba3ad84598350 Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Wed, 17 Aug 2022 06:59:46 -0500 Subject: New ui tests for new soft feature gates --- .../feature-gates/soft-syntax-gates-with-errors.rs | 30 ++++++++++++++++++++++ .../soft-syntax-gates-with-errors.stderr | 21 +++++++++++++++ .../soft-syntax-gates-without-errors.rs | 26 +++++++++++++++++++ .../soft-syntax-gates-without-errors.stderr | 24 +++++++++++++++++ src/test/ui/suggestions/many-type-ascription.rs | 4 +++ .../ui/suggestions/many-type-ascription.stderr | 12 +++++++++ .../suggestions/type-ascription-and-other-error.rs | 6 +++++ .../type-ascription-and-other-error.stderr | 8 ++++++ 8 files changed, 131 insertions(+) create mode 100644 src/test/ui/feature-gates/soft-syntax-gates-with-errors.rs create mode 100644 src/test/ui/feature-gates/soft-syntax-gates-with-errors.stderr create mode 100644 src/test/ui/feature-gates/soft-syntax-gates-without-errors.rs create mode 100644 src/test/ui/feature-gates/soft-syntax-gates-without-errors.stderr create mode 100644 src/test/ui/suggestions/many-type-ascription.rs create mode 100644 src/test/ui/suggestions/many-type-ascription.stderr create mode 100644 src/test/ui/suggestions/type-ascription-and-other-error.rs create mode 100644 src/test/ui/suggestions/type-ascription-and-other-error.stderr diff --git a/src/test/ui/feature-gates/soft-syntax-gates-with-errors.rs b/src/test/ui/feature-gates/soft-syntax-gates-with-errors.rs new file mode 100644 index 00000000000..49f1cba7151 --- /dev/null +++ b/src/test/ui/feature-gates/soft-syntax-gates-with-errors.rs @@ -0,0 +1,30 @@ +// check-fail +// This file is used to test the behavior of the early-pass syntax warnings. +// If macro syntax is stabilized, replace with a different unstable syntax. + +macro a() {} +//~^ ERROR: `macro` is experimental + +#[cfg(FALSE)] +macro b() {} + +macro_rules! identity { + ($($x:tt)*) => ($($x)*); +} + +identity! { + macro c() {} + //~^ ERROR: `macro` is experimental +} + +#[cfg(FALSE)] +identity! { + macro d() {} // No error +} + +identity! { + #[cfg(FALSE)] + macro e() {} +} + +fn main() {} diff --git a/src/test/ui/feature-gates/soft-syntax-gates-with-errors.stderr b/src/test/ui/feature-gates/soft-syntax-gates-with-errors.stderr new file mode 100644 index 00000000000..49550d811ba --- /dev/null +++ b/src/test/ui/feature-gates/soft-syntax-gates-with-errors.stderr @@ -0,0 +1,21 @@ +error[E0658]: `macro` is experimental + --> $DIR/soft-syntax-gates-with-errors.rs:5:1 + | +LL | macro a() {} + | ^^^^^^^^^^^^ + | + = note: see issue #39412 for more information + = help: add `#![feature(decl_macro)]` to the crate attributes to enable + +error[E0658]: `macro` is experimental + --> $DIR/soft-syntax-gates-with-errors.rs:16:5 + | +LL | macro c() {} + | ^^^^^^^^^^^^ + | + = note: see issue #39412 for more information + = help: add `#![feature(decl_macro)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/soft-syntax-gates-without-errors.rs b/src/test/ui/feature-gates/soft-syntax-gates-without-errors.rs new file mode 100644 index 00000000000..ca4ad2320f6 --- /dev/null +++ b/src/test/ui/feature-gates/soft-syntax-gates-without-errors.rs @@ -0,0 +1,26 @@ +// check-pass +// This file is used to test the behavior of the early-pass syntax warnings. +// If macro syntax is stabilized, replace with a different unstable syntax. + +#[cfg(FALSE)] +macro b() {} +//~^ WARN: `macro` is experimental +//~| WARN: unstable syntax + +macro_rules! identity { + ($($x:tt)*) => ($($x)*); +} + +#[cfg(FALSE)] +identity! { + macro d() {} // No error +} + +identity! { + #[cfg(FALSE)] + macro e() {} + //~^ WARN: `macro` is experimental + //~| WARN: unstable syntax +} + +fn main() {} diff --git a/src/test/ui/feature-gates/soft-syntax-gates-without-errors.stderr b/src/test/ui/feature-gates/soft-syntax-gates-without-errors.stderr new file mode 100644 index 00000000000..3d9c22e5487 --- /dev/null +++ b/src/test/ui/feature-gates/soft-syntax-gates-without-errors.stderr @@ -0,0 +1,24 @@ +warning: `macro` is experimental + --> $DIR/soft-syntax-gates-without-errors.rs:6:1 + | +LL | macro b() {} + | ^^^^^^^^^^^^ + | + = note: see issue #39412 for more information + = help: add `#![feature(decl_macro)]` to the crate attributes to enable + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: `macro` is experimental + --> $DIR/soft-syntax-gates-without-errors.rs:21:5 + | +LL | macro e() {} + | ^^^^^^^^^^^^ + | + = note: see issue #39412 for more information + = help: add `#![feature(decl_macro)]` to the crate attributes to enable + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: 2 warnings emitted + diff --git a/src/test/ui/suggestions/many-type-ascription.rs b/src/test/ui/suggestions/many-type-ascription.rs new file mode 100644 index 00000000000..31ac556b944 --- /dev/null +++ b/src/test/ui/suggestions/many-type-ascription.rs @@ -0,0 +1,4 @@ +fn main() { + let _ = 0: i32; //~ ERROR: type ascription is experimental + let _ = 0: i32; // (error only emitted once) +} diff --git a/src/test/ui/suggestions/many-type-ascription.stderr b/src/test/ui/suggestions/many-type-ascription.stderr new file mode 100644 index 00000000000..3706bbae9df --- /dev/null +++ b/src/test/ui/suggestions/many-type-ascription.stderr @@ -0,0 +1,12 @@ +error[E0658]: type ascription is experimental + --> $DIR/many-type-ascription.rs:2:13 + | +LL | let _ = 0: i32; + | ^^^^^^ + | + = note: see issue #23416 for more information + = help: add `#![feature(type_ascription)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/suggestions/type-ascription-and-other-error.rs b/src/test/ui/suggestions/type-ascription-and-other-error.rs new file mode 100644 index 00000000000..99ab2f3c858 --- /dev/null +++ b/src/test/ui/suggestions/type-ascription-and-other-error.rs @@ -0,0 +1,6 @@ +fn main() { + not rust; //~ ERROR + let _ = 0: i32; // (error hidden by existing error) + #[cfg(FALSE)] + let _ = 0: i32; // (warning hidden by existing error) +} diff --git a/src/test/ui/suggestions/type-ascription-and-other-error.stderr b/src/test/ui/suggestions/type-ascription-and-other-error.stderr new file mode 100644 index 00000000000..eadf634bb14 --- /dev/null +++ b/src/test/ui/suggestions/type-ascription-and-other-error.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `rust` + --> $DIR/type-ascription-and-other-error.rs:2:9 + | +LL | not rust; + | ^^^^ expected one of 8 possible tokens + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From 701b2747c331fb311ab67e50519bb226d86b76dc Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 17 Aug 2022 13:03:32 +0000 Subject: Remove optimize_function It currently doesn't have any optimizations at all. --- src/base.rs | 13 +------------ src/optimize/mod.rs | 17 ----------------- 2 files changed, 1 insertion(+), 29 deletions(-) diff --git a/src/base.rs b/src/base.rs index c68d33465bc..2603da19182 100644 --- a/src/base.rs +++ b/src/base.rs @@ -148,7 +148,7 @@ fn compile_fn<'tcx>( ) { let tcx = cx.tcx; - let mut clif_comments = codegened_func.clif_comments; + let clif_comments = codegened_func.clif_comments; // Store function in context let context = cached_context; @@ -165,17 +165,6 @@ fn compile_fn<'tcx>( // invalidate it when it would change. context.domtree.clear(); - // Perform rust specific optimizations - tcx.sess.time("optimize clif ir", || { - crate::optimize::optimize_function( - tcx, - module.isa(), - codegened_func.instance, - context, - &mut clif_comments, - ); - }); - #[cfg(any())] // This is never true let _clif_guard = { use std::fmt::Write; diff --git a/src/optimize/mod.rs b/src/optimize/mod.rs index d1f89adb3bb..0df7e82294b 100644 --- a/src/optimize/mod.rs +++ b/src/optimize/mod.rs @@ -1,20 +1,3 @@ //! Various optimizations specific to cg_clif -use cranelift_codegen::isa::TargetIsa; - -use crate::prelude::*; - pub(crate) mod peephole; - -pub(crate) fn optimize_function<'tcx>( - tcx: TyCtxt<'tcx>, - isa: &dyn TargetIsa, - instance: Instance<'tcx>, - ctx: &mut Context, - clif_comments: &mut crate::pretty_clif::CommentWriter, -) { - // FIXME classify optimizations over opt levels once we have more - - crate::pretty_clif::write_clif_file(tcx, "preopt", isa, instance, &ctx.func, &*clif_comments); - crate::base::verify_func(tcx, &*clif_comments, &ctx.func); -} -- cgit 1.4.1-3-g733a5 From b181f2b3769f1185d328efb1569c3da72e5edaa0 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 17 Aug 2022 13:07:18 +0000 Subject: Replace instance param of write_clif_file with symbol_name --- src/base.rs | 6 +++--- src/pretty_clif.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/base.rs b/src/base.rs index 2603da19182..85cdc6824a6 100644 --- a/src/base.rs +++ b/src/base.rs @@ -119,9 +119,9 @@ fn codegen_fn<'tcx>( crate::pretty_clif::write_clif_file( tcx, + symbol_name.name, "unopt", module.isa(), - instance, &func, &clif_comments, ); @@ -201,9 +201,9 @@ fn compile_fn<'tcx>( // Write optimized function to file for debugging crate::pretty_clif::write_clif_file( tcx, + codegened_func.symbol_name.name, "opt", module.isa(), - codegened_func.instance, &context.func, &clif_comments, ); @@ -211,7 +211,7 @@ fn compile_fn<'tcx>( if let Some(disasm) = &context.mach_compile_result.as_ref().unwrap().disasm { crate::pretty_clif::write_ir_file( tcx, - || format!("{}.vcode", tcx.symbol_name(codegened_func.instance).name), + || format!("{}.vcode", codegened_func.symbol_name.name), |file| file.write_all(disasm.as_bytes()), ) } diff --git a/src/pretty_clif.rs b/src/pretty_clif.rs index 1d1ec21680e..0081ec842eb 100644 --- a/src/pretty_clif.rs +++ b/src/pretty_clif.rs @@ -231,16 +231,16 @@ pub(crate) fn write_ir_file( pub(crate) fn write_clif_file<'tcx>( tcx: TyCtxt<'tcx>, + symbol_name: &str, postfix: &str, isa: &dyn cranelift_codegen::isa::TargetIsa, - instance: Instance<'tcx>, func: &cranelift_codegen::ir::Function, mut clif_comments: &CommentWriter, ) { // FIXME work around filename too long errors write_ir_file( tcx, - || format!("{}.{}.clif", tcx.symbol_name(instance).name, postfix), + || format!("{}.{}.clif", symbol_name, postfix), |file| { let mut clif = String::new(); cranelift_codegen::write::decorate_function(&mut clif_comments, &mut clif, func) -- cgit 1.4.1-3-g733a5 From c820b7cd607cd2fa7eec88785d92d10461b39053 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 17 Aug 2022 13:43:32 +0000 Subject: Remove TyCtxt field from CodegenCx --- src/base.rs | 66 ++++++++++++++++++++++++++++-------------------------- src/driver/aot.rs | 3 ++- src/driver/jit.rs | 10 ++++----- src/lib.rs | 7 ++++-- src/pretty_clif.rs | 59 ++++++++++++++++++++++-------------------------- 5 files changed, 73 insertions(+), 72 deletions(-) diff --git a/src/base.rs b/src/base.rs index 85cdc6824a6..6a276df40ba 100644 --- a/src/base.rs +++ b/src/base.rs @@ -24,22 +24,23 @@ struct CodegenedFunction<'tcx> { } pub(crate) fn codegen_and_compile_fn<'tcx>( + tcx: TyCtxt<'tcx>, cx: &mut crate::CodegenCx<'tcx>, cached_context: &mut Context, module: &mut dyn Module, instance: Instance<'tcx>, ) { - let tcx = cx.tcx; let _inst_guard = crate::PrintOnPanic(|| format!("{:?} {}", instance, tcx.symbol_name(instance).name)); let cached_func = std::mem::replace(&mut cached_context.func, Function::new()); - let codegened_func = codegen_fn(cx, cached_func, module, instance); + let codegened_func = codegen_fn(tcx, cx, cached_func, module, instance); - compile_fn(cx, cached_context, module, codegened_func); + compile_fn(tcx, cx, cached_context, module, codegened_func); } fn codegen_fn<'tcx>( + tcx: TyCtxt<'tcx>, cx: &mut crate::CodegenCx<'tcx>, cached_func: Function, module: &mut dyn Module, @@ -47,8 +48,6 @@ fn codegen_fn<'tcx>( ) -> CodegenedFunction<'tcx> { debug_assert!(!instance.substs.needs_infer()); - let tcx = cx.tcx; - let mir = tcx.instance_mir(instance.def); let _mir_guard = crate::PrintOnPanic(|| { let mut buf = Vec::new(); @@ -117,14 +116,16 @@ fn codegen_fn<'tcx>( fx.constants_cx.finalize(fx.tcx, &mut *fx.module); - crate::pretty_clif::write_clif_file( - tcx, - symbol_name.name, - "unopt", - module.isa(), - &func, - &clif_comments, - ); + if cx.should_write_ir { + crate::pretty_clif::write_clif_file( + tcx.output_filenames(()), + symbol_name.name, + "unopt", + module.isa(), + &func, + &clif_comments, + ); + } // Verify function verify_func(tcx, &clif_comments, &func); @@ -141,13 +142,12 @@ fn codegen_fn<'tcx>( } fn compile_fn<'tcx>( + tcx: TyCtxt<'tcx>, cx: &mut crate::CodegenCx<'tcx>, cached_context: &mut Context, module: &mut dyn Module, codegened_func: CodegenedFunction<'tcx>, ) { - let tcx = cx.tcx; - let clif_comments = codegened_func.clif_comments; // Store function in context @@ -194,26 +194,28 @@ fn compile_fn<'tcx>( // Define function tcx.sess.time("define function", || { - context.want_disasm = crate::pretty_clif::should_write_ir(tcx); + context.want_disasm = cx.should_write_ir; module.define_function(codegened_func.func_id, context).unwrap(); }); - // Write optimized function to file for debugging - crate::pretty_clif::write_clif_file( - tcx, - codegened_func.symbol_name.name, - "opt", - module.isa(), - &context.func, - &clif_comments, - ); - - if let Some(disasm) = &context.mach_compile_result.as_ref().unwrap().disasm { - crate::pretty_clif::write_ir_file( - tcx, - || format!("{}.vcode", codegened_func.symbol_name.name), - |file| file.write_all(disasm.as_bytes()), - ) + if cx.should_write_ir { + // Write optimized function to file for debugging + crate::pretty_clif::write_clif_file( + &cx.output_filenames, + codegened_func.symbol_name.name, + "opt", + module.isa(), + &context.func, + &clif_comments, + ); + + if let Some(disasm) = &context.mach_compile_result.as_ref().unwrap().disasm { + crate::pretty_clif::write_ir_file( + &cx.output_filenames, + &format!("{}.vcode", codegened_func.symbol_name.name), + |file| file.write_all(disasm.as_bytes()), + ) + } } // Define debuginfo for function diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 9d819e3995b..b2ad3cc4c4c 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -256,8 +256,9 @@ fn module_codegen( for (mono_item, _) in mono_items { match mono_item { MonoItem::Fn(inst) => { - cx.tcx.sess.time("codegen fn", || { + tcx.sess.time("codegen fn", || { crate::base::codegen_and_compile_fn( + tcx, &mut cx, &mut cached_context, &mut module, diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 1b046d7ec6e..de71b76da4e 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -129,8 +129,9 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { MonoItem::Fn(inst) => match backend_config.codegen_mode { CodegenMode::Aot => unreachable!(), CodegenMode::Jit => { - cx.tcx.sess.time("codegen fn", || { + tcx.sess.time("codegen fn", || { crate::base::codegen_and_compile_fn( + tcx, &mut cx, &mut cached_context, &mut jit_module, @@ -139,7 +140,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { }); } CodegenMode::JitLazy => { - codegen_shim(&mut cx, &mut cached_context, &mut jit_module, inst) + codegen_shim(tcx, &mut cached_context, &mut jit_module, inst) } }, MonoItem::Static(def_id) => { @@ -269,6 +270,7 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> ); tcx.sess.time("codegen fn", || { crate::base::codegen_and_compile_fn( + tcx, &mut cx, &mut Context::new(), jit_module, @@ -350,13 +352,11 @@ fn load_imported_symbols_for_jit( } fn codegen_shim<'tcx>( - cx: &mut CodegenCx<'tcx>, + tcx: TyCtxt<'tcx>, cached_context: &mut Context, module: &mut JITModule, inst: Instance<'tcx>, ) { - let tcx = cx.tcx; - let pointer_type = module.target_config().pointer_type(); let name = tcx.symbol_name(inst).name; diff --git a/src/lib.rs b/src/lib.rs index 909f4f00f1e..1e851e31ac3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,6 +26,7 @@ extern crate rustc_driver; use std::any::Any; use std::cell::{Cell, RefCell}; +use std::sync::Arc; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::CodegenResults; @@ -121,7 +122,8 @@ impl String> Drop for PrintOnPanic { /// The codegen context holds any information shared between the codegen of individual functions /// inside a single codegen unit with the exception of the Cranelift [`Module`](cranelift_module::Module). struct CodegenCx<'tcx> { - tcx: TyCtxt<'tcx>, + output_filenames: Arc, + should_write_ir: bool, global_asm: String, inline_asm_index: Cell, debug_context: Option>, @@ -147,7 +149,8 @@ impl<'tcx> CodegenCx<'tcx> { None }; CodegenCx { - tcx, + output_filenames: tcx.output_filenames(()).clone(), + should_write_ir: crate::pretty_clif::should_write_ir(tcx), global_asm: String::new(), inline_asm_index: Cell::new(0), debug_context, diff --git a/src/pretty_clif.rs b/src/pretty_clif.rs index 0081ec842eb..a7af162687c 100644 --- a/src/pretty_clif.rs +++ b/src/pretty_clif.rs @@ -62,7 +62,7 @@ use cranelift_codegen::{ }; use rustc_middle::ty::layout::FnAbiOf; -use rustc_session::config::OutputType; +use rustc_session::config::{OutputFilenames, OutputType}; use crate::prelude::*; @@ -205,15 +205,11 @@ pub(crate) fn should_write_ir(tcx: TyCtxt<'_>) -> bool { } pub(crate) fn write_ir_file( - tcx: TyCtxt<'_>, - name: impl FnOnce() -> String, + output_filenames: &OutputFilenames, + name: &str, write: impl FnOnce(&mut dyn Write) -> std::io::Result<()>, ) { - if !should_write_ir(tcx) { - return; - } - - let clif_output_dir = tcx.output_filenames(()).with_extension("clif"); + let clif_output_dir = output_filenames.with_extension("clif"); match std::fs::create_dir(&clif_output_dir) { Ok(()) => {} @@ -221,16 +217,20 @@ pub(crate) fn write_ir_file( res @ Err(_) => res.unwrap(), } - let clif_file_name = clif_output_dir.join(name()); + let clif_file_name = clif_output_dir.join(name); let res = std::fs::File::create(clif_file_name).and_then(|mut file| write(&mut file)); if let Err(err) = res { - tcx.sess.warn(&format!("error writing ir file: {}", err)); + // Using early_warn as no Session is available here + rustc_session::early_warn( + rustc_session::config::ErrorOutputType::default(), + &format!("error writing ir file: {}", err), + ); } } -pub(crate) fn write_clif_file<'tcx>( - tcx: TyCtxt<'tcx>, +pub(crate) fn write_clif_file( + output_filenames: &OutputFilenames, symbol_name: &str, postfix: &str, isa: &dyn cranelift_codegen::isa::TargetIsa, @@ -238,27 +238,22 @@ pub(crate) fn write_clif_file<'tcx>( mut clif_comments: &CommentWriter, ) { // FIXME work around filename too long errors - write_ir_file( - tcx, - || format!("{}.{}.clif", symbol_name, postfix), - |file| { - let mut clif = String::new(); - cranelift_codegen::write::decorate_function(&mut clif_comments, &mut clif, func) - .unwrap(); + write_ir_file(output_filenames, &format!("{}.{}.clif", symbol_name, postfix), |file| { + let mut clif = String::new(); + cranelift_codegen::write::decorate_function(&mut clif_comments, &mut clif, func).unwrap(); - for flag in isa.flags().iter() { - writeln!(file, "set {}", flag)?; - } - write!(file, "target {}", isa.triple().architecture.to_string())?; - for isa_flag in isa.isa_flags().iter() { - write!(file, " {}", isa_flag)?; - } - writeln!(file, "\n")?; - writeln!(file)?; - file.write_all(clif.as_bytes())?; - Ok(()) - }, - ); + for flag in isa.flags().iter() { + writeln!(file, "set {}", flag)?; + } + write!(file, "target {}", isa.triple().architecture.to_string())?; + for isa_flag in isa.isa_flags().iter() { + write!(file, " {}", isa_flag)?; + } + writeln!(file, "\n")?; + writeln!(file)?; + file.write_all(clif.as_bytes())?; + Ok(()) + }); } impl fmt::Debug for FunctionCx<'_, '_, '_> { -- cgit 1.4.1-3-g733a5 From 23747419ca52414d3ecf6f69f1e530e47ab1e937 Mon Sep 17 00:00:00 2001 From: Dezhi Wu Date: Wed, 17 Aug 2022 21:44:58 +0800 Subject: fix: a bunch of typos This PR will fix some typos detected by [typos]. There are also some other typos in the function names, variable names, and file names, which I leave as they are. I'm more certain that typos in comments should be fixed. [typos]: https://github.com/crate-ci/typos --- crates/flycheck/src/lib.rs | 2 +- crates/hir-def/src/nameres/proc_macro.rs | 2 +- crates/hir-expand/src/lib.rs | 2 +- crates/ide-assists/src/handlers/extract_module.rs | 6 +++--- .../src/handlers/replace_turbofish_with_explicit_type.rs | 2 +- crates/ide-assists/src/utils/suggest_name.rs | 4 ++-- crates/ide-completion/src/completions/postfix/format_like.rs | 4 ++-- crates/ide-completion/src/tests/flyimport.rs | 2 +- crates/ide-db/src/rename.rs | 2 +- crates/ide-diagnostics/src/handlers/missing_match_arms.rs | 2 +- crates/mbe/src/expander/matcher.rs | 2 +- crates/project-model/src/lib.rs | 2 +- crates/project-model/src/workspace.rs | 2 +- crates/rust-analyzer/src/bin/logger.rs | 2 +- crates/syntax/src/hacks.rs | 2 +- crates/vfs/src/lib.rs | 2 +- docs/dev/architecture.md | 2 +- editors/code/src/commands.ts | 2 +- editors/code/src/toolchain.ts | 2 +- 19 files changed, 23 insertions(+), 23 deletions(-) diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs index 3347940ec6d..2bebea2fbfe 100644 --- a/crates/flycheck/src/lib.rs +++ b/crates/flycheck/src/lib.rs @@ -345,7 +345,7 @@ impl CargoActor { // // Because cargo only outputs one JSON object per line, we can // simply skip a line if it doesn't parse, which just ignores any - // erroneus output. + // erroneous output. let mut error = String::new(); let mut read_at_least_one_message = false; diff --git a/crates/hir-def/src/nameres/proc_macro.rs b/crates/hir-def/src/nameres/proc_macro.rs index 5089ef2d817..52b79cd0fdd 100644 --- a/crates/hir-def/src/nameres/proc_macro.rs +++ b/crates/hir-def/src/nameres/proc_macro.rs @@ -45,7 +45,7 @@ impl Attrs { kind: ProcMacroKind::CustomDerive { helpers: Box::new([]) }, }), - // `#[proc_macro_derive(Trait, attibutes(helper1, helper2, ...))]` + // `#[proc_macro_derive(Trait, attributes(helper1, helper2, ...))]` [ TokenTree::Leaf(Leaf::Ident(trait_name)), TokenTree::Leaf(Leaf::Punct(comma)), diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs index f6b97fd5405..d753d88470c 100644 --- a/crates/hir-expand/src/lib.rs +++ b/crates/hir-expand/src/lib.rs @@ -616,7 +616,7 @@ impl ExpansionInfo { let token_id = match token_id_in_attr_input { Some(token_id) => token_id, - // the token is not inside an attribute's input so do the lookup in the macro_arg as ususal + // the token is not inside an attribute's input so do the lookup in the macro_arg as usual None => { let relative_range = token.value.text_range().checked_sub(self.arg.value.text_range().start())?; diff --git a/crates/ide-assists/src/handlers/extract_module.rs b/crates/ide-assists/src/handlers/extract_module.rs index b3c4d306ac1..897980c6650 100644 --- a/crates/ide-assists/src/handlers/extract_module.rs +++ b/crates/ide-assists/src/handlers/extract_module.rs @@ -29,7 +29,7 @@ use super::remove_unused_param::range_to_remove; // Assist: extract_module // -// Extracts a selected region as seperate module. All the references, visibility and imports are +// Extracts a selected region as separate module. All the references, visibility and imports are // resolved. // // ``` @@ -105,7 +105,7 @@ pub(crate) fn extract_module(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti // //- Thirdly, resolving all the imports this includes removing paths from imports // outside the module, shifting/cloning them inside new module, or shifting the imports, or making - // new import statemnts + // new import statements //We are getting item usages and record_fields together, record_fields //for change_visibility and usages for first point mentioned above in the process @@ -661,7 +661,7 @@ fn check_intersection_and_push( import_path: TextRange, ) { if import_paths_to_be_removed.len() > 0 { - // Text ranges recieved here for imports are extended to the + // Text ranges received here for imports are extended to the // next/previous comma which can cause intersections among them // and later deletion of these can cause panics similar // to reported in #11766. So to mitigate it, we diff --git a/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs b/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs index 6112e09455a..5242f3b5100 100644 --- a/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs +++ b/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs @@ -88,7 +88,7 @@ pub(crate) fn replace_turbofish_with_explicit_type( }, ); } else if let Some(InferType(t)) = let_stmt.ty() { - // If there's a type inferrence underscore, we can offer to replace it with the type in + // If there's a type inference underscore, we can offer to replace it with the type in // the turbofish. // let x: _ = fn::<...>(); let underscore_range = t.syntax().text_range(); diff --git a/crates/ide-assists/src/utils/suggest_name.rs b/crates/ide-assists/src/utils/suggest_name.rs index 779cdbc93c5..662ddd063f3 100644 --- a/crates/ide-assists/src/utils/suggest_name.rs +++ b/crates/ide-assists/src/utils/suggest_name.rs @@ -75,7 +75,7 @@ pub(crate) fn for_generic_parameter(ty: &ast::ImplTraitType) -> SmolStr { /// In current implementation, the function tries to get the name from /// the following sources: /// -/// * if expr is an argument to function/method, use paramter name +/// * if expr is an argument to function/method, use parameter name /// * if expr is a function/method call, use function name /// * expression type name if it exists (E.g. `()`, `fn() -> ()` or `!` do not have names) /// * fallback: `var_name` @@ -85,7 +85,7 @@ pub(crate) fn for_generic_parameter(ty: &ast::ImplTraitType) -> SmolStr { /// Currently it sticks to the first name found. // FIXME: Microoptimize and return a `SmolStr` here. pub(crate) fn for_variable(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> String { - // `from_param` does not benifit from stripping + // `from_param` does not benefit from stripping // it need the largest context possible // so we check firstmost if let Some(name) = from_param(expr, sema) { diff --git a/crates/ide-completion/src/completions/postfix/format_like.rs b/crates/ide-completion/src/completions/postfix/format_like.rs index 6b94347e0ad..b273a4cb53b 100644 --- a/crates/ide-completion/src/completions/postfix/format_like.rs +++ b/crates/ide-completion/src/completions/postfix/format_like.rs @@ -173,7 +173,7 @@ impl FormatStrParser { } } (State::Expr, ':') if chars.peek().copied() == Some(':') => { - // path seperator + // path separator current_expr.push_str("::"); chars.next(); } @@ -185,7 +185,7 @@ impl FormatStrParser { current_expr = String::new(); self.state = State::FormatOpts; } else { - // We're inside of braced expression, assume that it's a struct field name/value delimeter. + // We're inside of braced expression, assume that it's a struct field name/value delimiter. current_expr.push(chr); } } diff --git a/crates/ide-completion/src/tests/flyimport.rs b/crates/ide-completion/src/tests/flyimport.rs index 0bba7f2459c..a63ef006875 100644 --- a/crates/ide-completion/src/tests/flyimport.rs +++ b/crates/ide-completion/src/tests/flyimport.rs @@ -159,7 +159,7 @@ pub mod some_module { pub struct ThiiiiiirdStruct; // contains all letters from the query, but not in the beginning, displayed second pub struct AfterThirdStruct; - // contains all letters from the query in the begginning, displayed first + // contains all letters from the query in the beginning, displayed first pub struct ThirdStruct; } diff --git a/crates/ide-db/src/rename.rs b/crates/ide-db/src/rename.rs index 517fe3f246d..49b81265ea5 100644 --- a/crates/ide-db/src/rename.rs +++ b/crates/ide-db/src/rename.rs @@ -82,7 +82,7 @@ impl Definition { } /// Textual range of the identifier which will change when renaming this - /// `Definition`. Note that some definitions, like buitin types, can't be + /// `Definition`. Note that some definitions, like builtin types, can't be /// renamed. pub fn range_for_rename(self, sema: &Semantics<'_, RootDatabase>) -> Option { let res = match self { diff --git a/crates/ide-diagnostics/src/handlers/missing_match_arms.rs b/crates/ide-diagnostics/src/handlers/missing_match_arms.rs index 9e66fbfb752..5fcaf405b14 100644 --- a/crates/ide-diagnostics/src/handlers/missing_match_arms.rs +++ b/crates/ide-diagnostics/src/handlers/missing_match_arms.rs @@ -750,7 +750,7 @@ fn main() { enum Foo { A } fn main() { // FIXME: this should not bail out but current behavior is such as the old algorithm. - // ExprValidator::validate_match(..) checks types of top level patterns incorrecly. + // ExprValidator::validate_match(..) checks types of top level patterns incorrectly. match Foo::A { ref _x => {} Foo::A => {} diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs index 5020e9abaf3..c1aa14d6b7e 100644 --- a/crates/mbe/src/expander/matcher.rs +++ b/crates/mbe/src/expander/matcher.rs @@ -321,7 +321,7 @@ struct MatchState<'t> { /// The KleeneOp of this sequence if we are in a repetition. sep_kind: Option, - /// Number of tokens of seperator parsed + /// Number of tokens of separator parsed sep_parsed: Option, /// Matched meta variables bindings diff --git a/crates/project-model/src/lib.rs b/crates/project-model/src/lib.rs index e3f83084ac8..b81b7432f65 100644 --- a/crates/project-model/src/lib.rs +++ b/crates/project-model/src/lib.rs @@ -3,7 +3,7 @@ //! //! Pure model is represented by the [`base_db::CrateGraph`] from another crate. //! -//! In this crate, we are conserned with "real world" project models. +//! In this crate, we are concerned with "real world" project models. //! //! Specifically, here we have a representation for a Cargo project //! ([`CargoWorkspace`]) and for manually specified layout ([`ProjectJson`]). diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index daabb299f76..8d6f50f5587 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -770,7 +770,7 @@ fn handle_rustc_crates( queue.push_back(root_pkg); while let Some(pkg) = queue.pop_front() { // Don't duplicate packages if they are dependended on a diamond pattern - // N.B. if this line is ommitted, we try to analyse over 4_800_000 crates + // N.B. if this line is omitted, we try to analyse over 4_800_000 crates // which is not ideal if rustc_pkg_crates.contains_key(&pkg) { continue; diff --git a/crates/rust-analyzer/src/bin/logger.rs b/crates/rust-analyzer/src/bin/logger.rs index 0b69f75bc0d..298814af5a4 100644 --- a/crates/rust-analyzer/src/bin/logger.rs +++ b/crates/rust-analyzer/src/bin/logger.rs @@ -52,7 +52,7 @@ impl Logger { // merge chalk filter to our main filter (from RA_LOG env). // // The acceptable syntax of CHALK_DEBUG is `target[span{field=value}]=level`. - // As the value should only affect chalk crates, we'd better mannually + // As the value should only affect chalk crates, we'd better manually // specify the target. And for simplicity, CHALK_DEBUG only accept the value // that specify level. let chalk_level_dir = std::env::var("CHALK_DEBUG") diff --git a/crates/syntax/src/hacks.rs b/crates/syntax/src/hacks.rs index a047f61fa03..ec3d3d444c3 100644 --- a/crates/syntax/src/hacks.rs +++ b/crates/syntax/src/hacks.rs @@ -1,4 +1,4 @@ -//! Things which exist to solve practial issues, but which shouldn't exist. +//! Things which exist to solve practical issues, but which shouldn't exist. //! //! Please avoid adding new usages of the functions in this module diff --git a/crates/vfs/src/lib.rs b/crates/vfs/src/lib.rs index 10fae41d081..7badb1c363b 100644 --- a/crates/vfs/src/lib.rs +++ b/crates/vfs/src/lib.rs @@ -64,7 +64,7 @@ pub struct FileId(pub u32); /// Storage for all files read by rust-analyzer. /// -/// For more informations see the [crate-level](crate) documentation. +/// For more information see the [crate-level](crate) documentation. #[derive(Default)] pub struct Vfs { interner: PathInterner, diff --git a/docs/dev/architecture.md b/docs/dev/architecture.md index 51e26c58a91..c173a239fea 100644 --- a/docs/dev/architecture.md +++ b/docs/dev/architecture.md @@ -485,7 +485,7 @@ Mind the code--architecture gap: at the moment, we are using fewer feature flags ### Serialization In Rust, it is easy (often too easy) to add serialization to any type by adding `#[derive(Serialize)]`. -This easiness is misleading -- serializable types impose significant backwards compatability constraints. +This easiness is misleading -- serializable types impose significant backwards compatibility constraints. If a type is serializable, then it is a part of some IPC boundary. You often don't control the other side of this boundary, so changing serializable types is hard. diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts index f58de9da1bf..12f666401fd 100644 --- a/editors/code/src/commands.ts +++ b/editors/code/src/commands.ts @@ -655,7 +655,7 @@ function crateGraph(ctx: Ctx, full: boolean): Cmd { html, body { margin:0; padding:0; overflow:hidden } svg { position:fixed; top:0; left:0; height:100%; width:100% } - /* Disable the graphviz backgroud and fill the polygons */ + /* Disable the graphviz background and fill the polygons */ .graph > polygon { display:none; } :is(.node,.edge) polygon { fill: white; } diff --git a/editors/code/src/toolchain.ts b/editors/code/src/toolchain.ts index bac163da9f3..e1ca4954280 100644 --- a/editors/code/src/toolchain.ts +++ b/editors/code/src/toolchain.ts @@ -158,7 +158,7 @@ export const getPathForExecutable = memoizeAsync( try { // hmm, `os.homedir()` seems to be infallible - // it is not mentioned in docs and cannot be infered by the type signature... + // it is not mentioned in docs and cannot be inferred by the type signature... const standardPath = vscode.Uri.joinPath( vscode.Uri.file(os.homedir()), ".cargo", -- cgit 1.4.1-3-g733a5 From 2079b4bb0890f4ac806fa7f8cbe16e3c64ba9bee Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Wed, 17 Aug 2022 14:46:05 +0100 Subject: Use `stack_store` instead of `stack_addr`+`store` when building structs --- src/abi/pass_mode.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/abi/pass_mode.rs b/src/abi/pass_mode.rs index 2f8c697bd1e..3192575b8ad 100644 --- a/src/abi/pass_mode.rs +++ b/src/abi/pass_mode.rs @@ -193,7 +193,7 @@ pub(super) fn from_casted_value<'tcx>( // larger alignment than the integer. size: (std::cmp::max(abi_param_size, layout_size) + 15) / 16 * 16, }); - let ptr = Pointer::new(fx.bcx.ins().stack_addr(pointer_ty(fx.tcx), stack_slot, 0)); + let ptr = Pointer::stack_slot(stack_slot); let mut offset = 0; let mut block_params_iter = block_params.iter().copied(); for param in abi_params { -- cgit 1.4.1-3-g733a5 From df1b25171c8b2b209d1c667ea8a2e41a81c108f2 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 17 Aug 2022 13:47:52 +0000 Subject: Remove TyCtxt parameter from compile_fn --- src/base.rs | 7 +++---- src/lib.rs | 3 +++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/base.rs b/src/base.rs index 6a276df40ba..a7c7f66e166 100644 --- a/src/base.rs +++ b/src/base.rs @@ -36,7 +36,7 @@ pub(crate) fn codegen_and_compile_fn<'tcx>( let cached_func = std::mem::replace(&mut cached_context.func, Function::new()); let codegened_func = codegen_fn(tcx, cx, cached_func, module, instance); - compile_fn(tcx, cx, cached_context, module, codegened_func); + compile_fn(cx, cached_context, module, codegened_func); } fn codegen_fn<'tcx>( @@ -142,7 +142,6 @@ fn codegen_fn<'tcx>( } fn compile_fn<'tcx>( - tcx: TyCtxt<'tcx>, cx: &mut crate::CodegenCx<'tcx>, cached_context: &mut Context, module: &mut dyn Module, @@ -193,7 +192,7 @@ fn compile_fn<'tcx>( }; // Define function - tcx.sess.time("define function", || { + cx.profiler.verbose_generic_activity("define function").run(|| { context.want_disasm = cx.should_write_ir; module.define_function(codegened_func.func_id, context).unwrap(); }); @@ -222,7 +221,7 @@ fn compile_fn<'tcx>( let isa = module.isa(); let debug_context = &mut cx.debug_context; let unwind_context = &mut cx.unwind_context; - tcx.sess.time("generate debug info", || { + cx.profiler.verbose_generic_activity("generate debug info").run(|| { if let Some(debug_context) = debug_context { debug_context.define_function( codegened_func.instance, diff --git a/src/lib.rs b/src/lib.rs index 1e851e31ac3..f4ffbbcf86e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,6 +30,7 @@ use std::sync::Arc; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::CodegenResults; +use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::ErrorGuaranteed; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; @@ -122,6 +123,7 @@ impl String> Drop for PrintOnPanic { /// The codegen context holds any information shared between the codegen of individual functions /// inside a single codegen unit with the exception of the Cranelift [`Module`](cranelift_module::Module). struct CodegenCx<'tcx> { + profiler: SelfProfilerRef, output_filenames: Arc, should_write_ir: bool, global_asm: String, @@ -149,6 +151,7 @@ impl<'tcx> CodegenCx<'tcx> { None }; CodegenCx { + profiler: tcx.prof.clone(), output_filenames: tcx.output_filenames(()).clone(), should_write_ir: crate::pretty_clif::should_write_ir(tcx), global_asm: String::new(), -- cgit 1.4.1-3-g733a5 From 736288f221ac9578f88a0c1d001f8febe0d33496 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 17 Aug 2022 18:14:25 +0200 Subject: dedup some code --- .../rustc_trait_selection/src/traits/engine.rs | 23 +++++++++++++++++++++- compiler/rustc_typeck/src/check/compare_method.rs | 13 +++--------- compiler/rustc_typeck/src/check/wfcheck.rs | 12 ++--------- .../src/impl_wf_check/min_specialization.rs | 14 +++---------- 4 files changed, 30 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 6c177f63887..136b9432145 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -3,7 +3,8 @@ use std::cell::RefCell; use super::TraitEngine; use super::{ChalkFulfillmentContext, FulfillmentContext}; use crate::infer::InferCtxtExt; -use rustc_hir::def_id::DefId; +use rustc_data_structures::fx::FxHashSet; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::{InferCtxt, InferOk}; use rustc_infer::traits::{ FulfillmentError, Obligation, ObligationCause, PredicateObligation, TraitEngineExt as _, @@ -12,6 +13,7 @@ use rustc_middle::ty::error::TypeError; use rustc_middle::ty::ToPredicate; use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::Span; pub trait TraitEngineExt<'tcx> { fn new(tcx: TyCtxt<'tcx>) -> Box; @@ -109,4 +111,23 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { pub fn select_all_or_error(&self) -> Vec> { self.engine.borrow_mut().select_all_or_error(self.infcx) } + + pub fn assumed_wf_types( + &self, + param_env: ty::ParamEnv<'tcx>, + span: Span, + def_id: LocalDefId, + ) -> FxHashSet> { + let tcx = self.infcx.tcx; + let assumed_wf_types = tcx.assumed_wf_types(def_id); + let mut implied_bounds = FxHashSet::default(); + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let cause = ObligationCause::misc(span, hir_id); + for ty in assumed_wf_types { + implied_bounds.insert(ty); + let normalized = self.normalize(cause.clone(), param_env, ty); + implied_bounds.insert(normalized); + } + implied_bounds + } } diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 0716b3bc670..e42f18db1f5 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1454,15 +1454,8 @@ pub fn check_type_bounds<'tcx>( tcx.infer_ctxt().enter(move |infcx| { let ocx = ObligationCtxt::new(&infcx); - let assumed_wf_types = tcx.assumed_wf_types(impl_ty.def_id); - let mut implied_bounds = FxHashSet::default(); - let cause = ObligationCause::misc(impl_ty_span, impl_ty_hir_id); - for ty in assumed_wf_types { - implied_bounds.insert(ty); - let normalized = ocx.normalize(cause.clone(), param_env, ty); - implied_bounds.insert(normalized); - } - let implied_bounds = implied_bounds; + let assumed_wf_types = + ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty.def_id.expect_local()); let mut selcx = traits::SelectionContext::new(&infcx); let normalize_cause = ObligationCause::new( @@ -1521,7 +1514,7 @@ pub fn check_type_bounds<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. let mut outlives_environment = OutlivesEnvironment::new(param_env); - outlives_environment.add_implied_bounds(&infcx, implied_bounds, impl_ty_hir_id); + outlives_environment.add_implied_bounds(&infcx, assumed_wf_types, impl_ty_hir_id); infcx.check_region_obligations_and_report_errors( impl_ty.def_id.expect_local(), &outlives_environment, diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 2ac183b504e..4814aea7afb 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -90,15 +90,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( tcx.infer_ctxt().enter(|ref infcx| { let ocx = ObligationCtxt::new(infcx); - let assumed_wf_types = tcx.assumed_wf_types(body_def_id); - let mut implied_bounds = FxHashSet::default(); - let cause = ObligationCause::misc(span, body_id); - for ty in assumed_wf_types { - implied_bounds.insert(ty); - let normalized = ocx.normalize(cause.clone(), param_env, ty); - implied_bounds.insert(normalized); - } - let implied_bounds = implied_bounds; + let assumed_wf_types = ocx.assumed_wf_types(param_env, span, body_def_id); let mut wfcx = WfCheckingCtxt { ocx, span, body_id, param_env }; @@ -113,7 +105,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( } let mut outlives_environment = OutlivesEnvironment::new(param_env); - outlives_environment.add_implied_bounds(infcx, implied_bounds, body_id); + outlives_environment.add_implied_bounds(infcx, assumed_wf_types, body_id); infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment); }) } diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs index cc8453bf1d0..97346f0f834 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -74,7 +74,6 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::specialization_graph::Node; -use rustc_infer::traits::ObligationCause; use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{self, TyCtxt, TypeVisitable}; @@ -145,15 +144,8 @@ fn get_impl_substs<'tcx>( let param_env = tcx.param_env(impl1_def_id); let impl1_hir_id = tcx.hir().local_def_id_to_hir_id(impl1_def_id); - let assumed_wf_types = tcx.assumed_wf_types(impl1_def_id); - let mut implied_bounds = FxHashSet::default(); - let cause = ObligationCause::misc(tcx.def_span(impl1_def_id), impl1_hir_id); - for ty in assumed_wf_types { - implied_bounds.insert(ty); - let normalized = ocx.normalize(cause.clone(), param_env, ty); - implied_bounds.insert(normalized); - } - let implied_bounds = implied_bounds; + let assumed_wf_types = + ocx.assumed_wf_types(param_env, tcx.def_span(impl1_def_id), impl1_def_id); let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id.to_def_id()); let impl2_substs = @@ -166,7 +158,7 @@ fn get_impl_substs<'tcx>( } let mut outlives_env = OutlivesEnvironment::new(param_env); - outlives_env.add_implied_bounds(infcx, implied_bounds, impl1_hir_id); + outlives_env.add_implied_bounds(infcx, assumed_wf_types, impl1_hir_id); infcx.check_region_obligations_and_report_errors(impl1_def_id, &outlives_env); let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else { let span = tcx.def_span(impl1_def_id); -- cgit 1.4.1-3-g733a5 From e8499cfadcf17c051a33ab45a414b399f89a0a91 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Wed, 17 Aug 2022 10:06:24 +0200 Subject: Migrate "invalid variable declaration" errors to SessionDiagnostic --- .../rustc_error_messages/locales/en-US/parser.ftl | 9 +++++++ compiler/rustc_parse/src/parser/diagnostics.rs | 29 ++++++++++++++++++++ compiler/rustc_parse/src/parser/stmt.rs | 31 +++++++++------------- 3 files changed, 50 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index 7e583753618..2d378013dd0 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -32,3 +32,12 @@ parser_incorrect_use_of_await = parser_in_in_typo = expected iterable, found keyword `in` .suggestion = remove the duplicated `in` + +parser_invalid_variable_declaration = + invalid variable declaration + +parser_switch_mut_let_order = + switch the order of `mut` and `let` +parser_missing_let_before_mut = missing keyword +parser_use_let_not_auto = write `let` instead of `auto` to introduce a new variable +parser_use_let_not_var = write `let` instead of `var` to introduce a new variable diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 93e70e9abda..eeedfd157be 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -334,6 +334,35 @@ struct InInTypo { sugg_span: Span, } +#[derive(SessionDiagnostic)] +#[error(parser::invalid_variable_declaration)] +pub struct InvalidVariableDeclaration { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sub: InvalidVariableDeclarationSub, +} + +#[derive(SessionSubdiagnostic)] +pub enum InvalidVariableDeclarationSub { + #[suggestion( + parser::switch_mut_let_order, + applicability = "maybe-incorrect", + code = "let mut" + )] + SwitchMutLetOrder(#[primary_span] Span), + #[suggestion( + parser::missing_let_before_mut, + applicability = "machine-applicable", + code = "let mut" + )] + MissingLet(#[primary_span] Span), + #[suggestion(parser::use_let_not_auto, applicability = "machine-applicable", code = "let")] + UseLetNotAuto(#[primary_span] Span), + #[suggestion(parser::use_let_not_var, applicability = "machine-applicable", code = "let")] + UseLetNotVar(#[primary_span] Span), +} + // SnapshotParser is used to create a snapshot of the parser // without causing duplicate errors being emitted when the `Parser` // is dropped. diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index ade0f4fbc86..002547c6723 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -1,5 +1,7 @@ use super::attr::DEFAULT_INNER_ATTR_FORBIDDEN; -use super::diagnostics::{AttemptLocalParseRecovery, Error}; +use super::diagnostics::{ + AttemptLocalParseRecovery, Error, InvalidVariableDeclaration, InvalidVariableDeclarationSub, +}; use super::expr::LhsExpr; use super::pat::RecoverComma; use super::path::PathStyle; @@ -58,28 +60,22 @@ impl<'a> Parser<'a> { if self.token.is_keyword(kw::Mut) && self.is_keyword_ahead(1, &[kw::Let]) { self.bump(); let mut_let_span = lo.to(self.token.span); - self.struct_span_err(mut_let_span, "invalid variable declaration") - .span_suggestion( - mut_let_span, - "switch the order of `mut` and `let`", - "let mut", - Applicability::MaybeIncorrect, - ) - .emit(); + self.sess.emit_err(InvalidVariableDeclaration { + span: mut_let_span, + sub: InvalidVariableDeclarationSub::SwitchMutLetOrder(mut_let_span), + }); } Ok(Some(if self.token.is_keyword(kw::Let) { self.parse_local_mk(lo, attrs, capture_semi, force_collect)? } else if self.is_kw_followed_by_ident(kw::Mut) { - self.recover_stmt_local(lo, attrs, "missing keyword", "let mut")? + self.recover_stmt_local(lo, attrs, InvalidVariableDeclarationSub::MissingLet)? } else if self.is_kw_followed_by_ident(kw::Auto) { self.bump(); // `auto` - let msg = "write `let` instead of `auto` to introduce a new variable"; - self.recover_stmt_local(lo, attrs, msg, "let")? + self.recover_stmt_local(lo, attrs, InvalidVariableDeclarationSub::UseLetNotAuto)? } else if self.is_kw_followed_by_ident(sym::var) { self.bump(); // `var` - let msg = "write `let` instead of `var` to introduce a new variable"; - self.recover_stmt_local(lo, attrs, msg, "let")? + self.recover_stmt_local(lo, attrs, InvalidVariableDeclarationSub::UseLetNotVar)? } else if self.check_path() && !self.token.is_qpath_start() && !self.is_path_start_item() { // We have avoided contextual keywords like `union`, items with `crate` visibility, // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something @@ -217,13 +213,10 @@ impl<'a> Parser<'a> { &mut self, lo: Span, attrs: AttrWrapper, - msg: &str, - sugg: &str, + subdiagnostic: fn(Span) -> InvalidVariableDeclarationSub, ) -> PResult<'a, Stmt> { let stmt = self.recover_local_after_let(lo, attrs)?; - self.struct_span_err(lo, "invalid variable declaration") - .span_suggestion(lo, msg, sugg, Applicability::MachineApplicable) - .emit(); + self.sess.emit_err(InvalidVariableDeclaration { span: lo, sub: subdiagnostic(lo) }); Ok(stmt) } -- cgit 1.4.1-3-g733a5 From 86645c9cf7e7a73e01c006c8bc39c431cae0e8df Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 14 Aug 2022 11:28:28 +0200 Subject: Ignore substs when checking inlining history. --- compiler/rustc_mir_transform/src/inline.rs | 13 ++++++++---- src/test/mir-opt/inline/polymorphic-recursion.rs | 25 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 src/test/mir-opt/inline/polymorphic-recursion.rs diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 1e46b0a0e81..6704d3462f4 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -10,6 +10,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyCtxt}; use rustc_session::config::OptLevel; +use rustc_span::def_id::DefId; use rustc_span::{hygiene::ExpnKind, ExpnData, LocalExpnId, Span}; use rustc_target::spec::abi::Abi; @@ -103,8 +104,12 @@ struct Inliner<'tcx> { param_env: ParamEnv<'tcx>, /// Caller codegen attributes. codegen_fn_attrs: &'tcx CodegenFnAttrs, - /// Stack of inlined Instances. - history: Vec>, + /// Stack of inlined instances. + /// We only check the `DefId` and not the substs because we want to + /// avoid inlining cases of polymorphic recursion. + /// The number of `DefId`s is finite, so checking history is enough + /// to ensure that we do not loop endlessly while inlining. + history: Vec, /// Indicates that the caller body has been modified. changed: bool, } @@ -132,7 +137,7 @@ impl<'tcx> Inliner<'tcx> { Ok(new_blocks) => { debug!("inlined {}", callsite.callee); self.changed = true; - self.history.push(callsite.callee); + self.history.push(callsite.callee.def_id()); self.process_blocks(caller_body, new_blocks); self.history.pop(); } @@ -308,7 +313,7 @@ impl<'tcx> Inliner<'tcx> { return None; } - if self.history.contains(&callee) { + if self.history.contains(&callee.def_id()) { return None; } diff --git a/src/test/mir-opt/inline/polymorphic-recursion.rs b/src/test/mir-opt/inline/polymorphic-recursion.rs new file mode 100644 index 00000000000..7388722b776 --- /dev/null +++ b/src/test/mir-opt/inline/polymorphic-recursion.rs @@ -0,0 +1,25 @@ +// Make sure that the MIR inliner does not loop indefinitely on polymorphic recursion. +// compile-flags: --crate-type lib + +// Randomize `def_path_hash` by defining them under a module with different names +macro_rules! emit { + ($($m:ident)*) => {$( + pub mod $m { + pub trait Tr { type Next: Tr; } + + pub fn hoge() { + inner::(); + } + + #[inline(always)] + fn inner() + { + inner::(); + inner::(); + } + } + )*}; +} + +// Increase the chance of triggering the bug +emit!(m00 m01 m02 m03 m04 m05 m06 m07 m08 m09 m10 m11 m12 m13 m14 m15 m16 m17 m18 m19); -- cgit 1.4.1-3-g733a5 From 85b9568e2d7cc3c4b9a9d420ab3d4b91037bc6a5 Mon Sep 17 00:00:00 2001 From: Dorian Scheidt Date: Wed, 17 Aug 2022 11:57:14 -0500 Subject: feat: Run test mod from anywhere in parent file The "Run" feature of rust-analyzer is super useful, especially for running individual tests or test-modules during development. One common pattern in rust development is to develop tests in the same file as production code, inside a module (usually called `test` or `tests`) marked with `#[cfg(test)]`. Unforunately, this pattern is not well supported by r-a today, as a test module won't show up as a runnable unless the cursor is inside it. In my experience, it is quite common to want to run the tests associated with some production code immediately after editing it, not only after editing the tests themselves. As such it would be better if test modules were available from the "Run" menu even when the cursor is outside the test module. This change updates the filtration logic for runnables in `handlers::handle_runnables` to special case `RunnableKind::TestMod`, making test modules available regardless of the cursor location. Other `RunnableKind`s are unnaffected. Fixes #9589 --- crates/rust-analyzer/src/handlers.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index 943d043bc19..6337d49c240 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs @@ -703,10 +703,8 @@ pub(crate) fn handle_runnables( let mut res = Vec::new(); for runnable in snap.analysis.runnables(file_id)? { - if let Some(offset) = offset { - if !runnable.nav.full_range.contains_inclusive(offset) { - continue; - } + if should_skip_for_offset(&runnable, offset) { + continue; } if should_skip_target(&runnable, cargo_spec.as_ref()) { continue; @@ -772,6 +770,14 @@ pub(crate) fn handle_runnables( Ok(res) } +fn should_skip_for_offset(runnable: &Runnable, offset: Option) -> bool { + match offset { + None => false, + _ if matches!(&runnable.kind, RunnableKind::TestMod { .. }) => false, + Some(offset) => !runnable.nav.full_range.contains_inclusive(offset), + } +} + pub(crate) fn handle_related_tests( snap: GlobalStateSnapshot, params: lsp_types::TextDocumentPositionParams, -- cgit 1.4.1-3-g733a5 From be2641a61f2d34fe4f937a49dacfcb82bf0b9075 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 17 Aug 2022 20:22:52 +0200 Subject: Fortify check for const generics. --- compiler/rustc_typeck/src/astconv/mod.rs | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index ff81747cafe..5bb02bc246c 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1453,16 +1453,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .enumerate() .skip(1) // Remove `Self` for `ExistentialPredicate`. .map(|(index, arg)| { - if let ty::GenericArgKind::Type(ty) = arg.unpack() { - debug!(?ty); - if ty == dummy_self { - let param = &generics.params[index]; - missing_type_params.push(param.name); - return tcx.ty_error().into(); - } else if ty.walk().any(|arg| arg == dummy_self.into()) { - references_self = true; - return tcx.ty_error().into(); - } + if arg == dummy_self.into() { + let param = &generics.params[index]; + missing_type_params.push(param.name); + return tcx.ty_error().into(); + } else if arg.walk().any(|arg| arg == dummy_self.into()) { + references_self = true; + return tcx.ty_error().into(); } arg }) @@ -1509,10 +1506,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Like for trait refs, verify that `dummy_self` did not leak inside default type // parameters. let references_self = b.projection_ty.substs.iter().skip(1).any(|arg| { - if let ty::GenericArgKind::Type(ty) = arg.unpack() { - if ty == dummy_self || ty.walk().any(|arg| arg == dummy_self.into()) { - return true; - } + if arg.walk().any(|arg| arg == dummy_self.into()) { + return true; } false }); @@ -1524,7 +1519,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .substs .iter() .map(|arg| { - if let ty::GenericArgKind::Type(_) = arg.unpack() { + if arg.walk().any(|arg| arg == dummy_self.into()) { return tcx.ty_error().into(); } arg -- cgit 1.4.1-3-g733a5 From 64bd8c1dc427c8bcd69bed7c240b1f1f38bedbd3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 17 Aug 2022 19:02:55 +0000 Subject: Make same_type_modulo_infer a proper TypeRelation --- .../rustc_infer/src/infer/error_reporting/mod.rs | 132 ++++++++++++--------- compiler/rustc_middle/src/ty/sty.rs | 4 + src/test/ui/implied-bounds/issue-100690.rs | 45 +++++++ src/test/ui/implied-bounds/issue-100690.stderr | 22 ++++ 4 files changed, 150 insertions(+), 53 deletions(-) create mode 100644 src/test/ui/implied-bounds/issue-100690.rs create mode 100644 src/test/ui/implied-bounds/issue-100690.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 3c7dac2bfd8..d55708acc9a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -66,6 +66,7 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::Node; use rustc_middle::dep_graph::DepContext; use rustc_middle::ty::print::with_no_trimmed_paths; +use rustc_middle::ty::relate::{self, RelateResult, TypeRelation}; use rustc_middle::ty::{ self, error::TypeError, Binder, List, Region, Subst, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, @@ -2660,67 +2661,92 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// Float types, respectively). When comparing two ADTs, these rules apply recursively. pub fn same_type_modulo_infer(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { let (a, b) = self.resolve_vars_if_possible((a, b)); - match (a.kind(), b.kind()) { - (&ty::Adt(def_a, substs_a), &ty::Adt(def_b, substs_b)) => { - if def_a != def_b { - return false; - } + SameTypeModuloInfer(self).relate(a, b).is_ok() + } +} - substs_a - .types() - .zip(substs_b.types()) - .all(|(a, b)| self.same_type_modulo_infer(a, b)) - } - (&ty::FnDef(did_a, substs_a), &ty::FnDef(did_b, substs_b)) => { - if did_a != did_b { - return false; - } +struct SameTypeModuloInfer<'a, 'tcx>(&'a InferCtxt<'a, 'tcx>); - substs_a - .types() - .zip(substs_b.types()) - .all(|(a, b)| self.same_type_modulo_infer(a, b)) - } - (&ty::Int(_) | &ty::Uint(_), &ty::Infer(ty::InferTy::IntVar(_))) +impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.0.tcx + } + + fn param_env(&self) -> ty::ParamEnv<'tcx> { + // Unused, only for consts which we treat as always equal + ty::ParamEnv::empty() + } + + fn tag(&self) -> &'static str { + "SameTypeModuloInfer" + } + + fn a_is_expected(&self) -> bool { + true + } + + fn relate_with_variance>( + &mut self, + _variance: ty::Variance, + _info: ty::VarianceDiagInfo<'tcx>, + a: T, + b: T, + ) -> relate::RelateResult<'tcx, T> { + self.relate(a, b) + } + + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + match (a.kind(), b.kind()) { + (ty::Int(_) | ty::Uint(_), ty::Infer(ty::InferTy::IntVar(_))) | ( - &ty::Infer(ty::InferTy::IntVar(_)), - &ty::Int(_) | &ty::Uint(_) | &ty::Infer(ty::InferTy::IntVar(_)), + ty::Infer(ty::InferTy::IntVar(_)), + ty::Int(_) | ty::Uint(_) | ty::Infer(ty::InferTy::IntVar(_)), ) - | (&ty::Float(_), &ty::Infer(ty::InferTy::FloatVar(_))) + | (ty::Float(_), ty::Infer(ty::InferTy::FloatVar(_))) | ( - &ty::Infer(ty::InferTy::FloatVar(_)), - &ty::Float(_) | &ty::Infer(ty::InferTy::FloatVar(_)), + ty::Infer(ty::InferTy::FloatVar(_)), + ty::Float(_) | ty::Infer(ty::InferTy::FloatVar(_)), ) - | (&ty::Infer(ty::InferTy::TyVar(_)), _) - | (_, &ty::Infer(ty::InferTy::TyVar(_))) => true, - (&ty::Ref(_, ty_a, mut_a), &ty::Ref(_, ty_b, mut_b)) => { - mut_a == mut_b && self.same_type_modulo_infer(ty_a, ty_b) - } - (&ty::RawPtr(a), &ty::RawPtr(b)) => { - a.mutbl == b.mutbl && self.same_type_modulo_infer(a.ty, b.ty) - } - (&ty::Slice(a), &ty::Slice(b)) => self.same_type_modulo_infer(a, b), - (&ty::Array(a_ty, a_ct), &ty::Array(b_ty, b_ct)) => { - self.same_type_modulo_infer(a_ty, b_ty) && a_ct == b_ct - } - (&ty::Tuple(a), &ty::Tuple(b)) => { - if a.len() != b.len() { - return false; - } - std::iter::zip(a.iter(), b.iter()).all(|(a, b)| self.same_type_modulo_infer(a, b)) - } - (&ty::FnPtr(a), &ty::FnPtr(b)) => { - let a = a.skip_binder().inputs_and_output; - let b = b.skip_binder().inputs_and_output; - if a.len() != b.len() { - return false; - } - std::iter::zip(a.iter(), b.iter()).all(|(a, b)| self.same_type_modulo_infer(a, b)) - } - // FIXME(compiler-errors): This needs to be generalized more - _ => a == b, + | (ty::Infer(ty::InferTy::TyVar(_)), _) + | (_, ty::Infer(ty::InferTy::TyVar(_))) => Ok(a), + (ty::Infer(_), _) | (_, ty::Infer(_)) => Err(TypeError::Mismatch), + _ => relate::super_relate_tys(self, a, b), } } + + fn regions( + &mut self, + a: ty::Region<'tcx>, + b: ty::Region<'tcx>, + ) -> RelateResult<'tcx, ty::Region<'tcx>> { + if (a.is_var() && b.is_free_or_static()) || (b.is_var() && a.is_free_or_static()) || a == b + { + Ok(a) + } else { + Err(TypeError::Mismatch) + } + } + + fn binders( + &mut self, + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> relate::RelateResult<'tcx, ty::Binder<'tcx, T>> + where + T: relate::Relate<'tcx>, + { + Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?)) + } + + fn consts( + &mut self, + a: ty::Const<'tcx>, + _b: ty::Const<'tcx>, + ) -> relate::RelateResult<'tcx, ty::Const<'tcx>> { + // FIXME(compiler-errors): This could at least do some first-order + // relation + Ok(a) + } } impl<'a, 'tcx> InferCtxt<'a, 'tcx> { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 52c3a38861e..0070575f213 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1617,6 +1617,10 @@ impl<'tcx> Region<'tcx> { _ => self.is_free(), } } + + pub fn is_var(self) -> bool { + matches!(self.kind(), ty::ReVar(_)) + } } /// Type utilities diff --git a/src/test/ui/implied-bounds/issue-100690.rs b/src/test/ui/implied-bounds/issue-100690.rs new file mode 100644 index 00000000000..5599cd410ba --- /dev/null +++ b/src/test/ui/implied-bounds/issue-100690.rs @@ -0,0 +1,45 @@ +// This code (probably) _should_ compile, but it currently does not because we +// are not smart enough about implied bounds. + +use std::io; + +fn real_dispatch(f: F) -> Result<(), io::Error> +//~^ NOTE required by a bound in this +where + F: FnOnce(&mut UIView) -> Result<(), io::Error> + Send + 'static, + //~^ NOTE required by this bound in `real_dispatch` + //~| NOTE required by a bound in `real_dispatch` +{ + todo!() +} + +#[derive(Debug)] +struct UIView<'a, T: 'a> { + _phantom: std::marker::PhantomData<&'a mut T>, +} + +trait Handle<'a, T: 'a, V, R> { + fn dispatch(&self, f: F) -> Result<(), io::Error> + where + F: FnOnce(&mut V) -> R + Send + 'static; +} + +#[derive(Debug, Clone)] +struct TUIHandle { + _phantom: std::marker::PhantomData, +} + +impl<'a, T: 'a> Handle<'a, T, UIView<'a, T>, Result<(), io::Error>> for TUIHandle { + fn dispatch(&self, f: F) -> Result<(), io::Error> + where + F: FnOnce(&mut UIView<'a, T>) -> Result<(), io::Error> + Send + 'static, + { + real_dispatch(f) + //~^ ERROR expected a `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F` + //~| NOTE expected an `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F` + //~| NOTE expected a closure with arguments + //~| NOTE required by a bound introduced by this call + } +} + +fn main() {} diff --git a/src/test/ui/implied-bounds/issue-100690.stderr b/src/test/ui/implied-bounds/issue-100690.stderr new file mode 100644 index 00000000000..3f6af70d8ed --- /dev/null +++ b/src/test/ui/implied-bounds/issue-100690.stderr @@ -0,0 +1,22 @@ +error[E0277]: expected a `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F` + --> $DIR/issue-100690.rs:37:23 + | +LL | real_dispatch(f) + | ------------- ^ expected an `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F` + | | + | required by a bound introduced by this call + | + = note: expected a closure with arguments `(&mut UIView<'a, T>,)` + found a closure with arguments `(&mut UIView<'_, T>,)` +note: required by a bound in `real_dispatch` + --> $DIR/issue-100690.rs:9:8 + | +LL | fn real_dispatch(f: F) -> Result<(), io::Error> + | ------------- required by a bound in this +... +LL | F: FnOnce(&mut UIView) -> Result<(), io::Error> + Send + 'static, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `real_dispatch` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. -- cgit 1.4.1-3-g733a5 From 5145c970871e2dbe37228280fe34decd8c26ea4e Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 17 Aug 2022 12:09:59 -0700 Subject: Add LLVM15-specific codegen test for `try`/`?`s that now optimize away These still generated a bunch of code back in Rust 1.63 (), but with LLVM 15 merged they no longer do :tada: --- src/test/codegen/try_question_mark_nop.rs | 54 +++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/test/codegen/try_question_mark_nop.rs diff --git a/src/test/codegen/try_question_mark_nop.rs b/src/test/codegen/try_question_mark_nop.rs new file mode 100644 index 00000000000..d239387768e --- /dev/null +++ b/src/test/codegen/try_question_mark_nop.rs @@ -0,0 +1,54 @@ +// min-llvm-version: 15.0 +// compile-flags: -O -Z merge-functions=disabled --edition=2021 +// only-x86_64 + +#![crate_type = "lib"] +#![feature(try_blocks)] + +// These are now NOPs in LLVM 15, presumably thanks to nikic's change mentioned in +// . +// Unfortunately, as of 2022-08-17 they're not yet nops for `u64`s nor `Option`. + +use std::ops::ControlFlow::{self, Continue, Break}; + +// CHECK-LABEL: @result_nop_match_32 +#[no_mangle] +pub fn result_nop_match_32(x: Result) -> Result { + // CHECK: start + // CHECK-NEXT: ret i64 %0 + match x { + Ok(x) => Ok(x), + Err(x) => Err(x), + } +} + +// CHECK-LABEL: @result_nop_traits_32 +#[no_mangle] +pub fn result_nop_traits_32(x: Result) -> Result { + // CHECK: start + // CHECK-NEXT: ret i64 %0 + try { + x? + } +} + +// CHECK-LABEL: @control_flow_nop_match_32 +#[no_mangle] +pub fn control_flow_nop_match_32(x: ControlFlow) -> ControlFlow { + // CHECK: start + // CHECK-NEXT: ret i64 %0 + match x { + Continue(x) => Continue(x), + Break(x) => Break(x), + } +} + +// CHECK-LABEL: @control_flow_nop_traits_32 +#[no_mangle] +pub fn control_flow_nop_traits_32(x: ControlFlow) -> ControlFlow { + // CHECK: start + // CHECK-NEXT: ret i64 %0 + try { + x? + } +} -- cgit 1.4.1-3-g733a5 From 72acd94117e784d4e7425e827c60d6a6748d7a88 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 17 Aug 2022 21:50:59 +0200 Subject: Add const-generics test. --- src/test/ui/traits/alias/self-in-const-generics.rs | 12 ++++++++++++ src/test/ui/traits/alias/self-in-const-generics.stderr | 11 +++++++++++ 2 files changed, 23 insertions(+) create mode 100644 src/test/ui/traits/alias/self-in-const-generics.rs create mode 100644 src/test/ui/traits/alias/self-in-const-generics.stderr diff --git a/src/test/ui/traits/alias/self-in-const-generics.rs b/src/test/ui/traits/alias/self-in-const-generics.rs new file mode 100644 index 00000000000..b0de8ccd678 --- /dev/null +++ b/src/test/ui/traits/alias/self-in-const-generics.rs @@ -0,0 +1,12 @@ +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] +#![feature(trait_alias)] + +trait Bar {} + +trait BB = Bar<{ 2 + 1 }>; + +fn foo(x: &dyn BB) {} +//~^ ERROR the trait alias `BB` cannot be made into an object [E0038] + +fn main() {} diff --git a/src/test/ui/traits/alias/self-in-const-generics.stderr b/src/test/ui/traits/alias/self-in-const-generics.stderr new file mode 100644 index 00000000000..61cc217cfbc --- /dev/null +++ b/src/test/ui/traits/alias/self-in-const-generics.stderr @@ -0,0 +1,11 @@ +error[E0038]: the trait alias `BB` cannot be made into an object + --> $DIR/self-in-const-generics.rs:9:16 + | +LL | fn foo(x: &dyn BB) {} + | ^^ + | + = note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. -- cgit 1.4.1-3-g733a5 From 12abaf8ddde026fd733c7e783cc3081f4c22cce2 Mon Sep 17 00:00:00 2001 From: Ryo Yoshida Date: Thu, 18 Aug 2022 01:30:04 +0900 Subject: fix: resolve associated types of bare dyn types --- crates/hir-ty/src/lower.rs | 61 +++++++++++++++++---------------------- crates/hir-ty/src/tests/traits.rs | 28 ++++++++++++++++++ 2 files changed, 54 insertions(+), 35 deletions(-) diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 239f66bcb7e..ae115c8c0da 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -238,18 +238,7 @@ impl<'a> TyLoweringContext<'a> { }) .intern(Interner) } - TypeRef::DynTrait(bounds) => { - let self_ty = - TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner); - let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { - QuantifiedWhereClauses::from_iter( - Interner, - bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)), - ) - }); - let bounds = crate::make_single_type_binders(bounds); - TyKind::Dyn(DynTy { bounds, lifetime: static_lifetime() }).intern(Interner) - } + TypeRef::DynTrait(bounds) => self.lower_dyn_trait(bounds), TypeRef::ImplTrait(bounds) => { match self.impl_trait_mode { ImplTraitLoweringMode::Opaque => { @@ -468,29 +457,10 @@ impl<'a> TyLoweringContext<'a> { } } 0 => { - let self_ty = Some( - TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) - .intern(Interner), - ); - let trait_ref = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { - ctx.lower_trait_ref_from_resolved_path( - trait_, - resolved_segment, - self_ty, - ) - }); - let dyn_ty = DynTy { - bounds: crate::make_single_type_binders( - QuantifiedWhereClauses::from_iter( - Interner, - Some(crate::wrap_empty_binders(WhereClause::Implemented( - trait_ref, - ))), - ), - ), - lifetime: static_lifetime(), - }; - TyKind::Dyn(dyn_ty).intern(Interner) + // Trait object type without dyn; this should be handled in upstream. See + // `lower_path()`. + stdx::never!("unexpected fully resolved trait path"); + TyKind::Error.intern(Interner) } _ => { // FIXME report error (ambiguous associated type) @@ -555,11 +525,20 @@ impl<'a> TyLoweringContext<'a> { let (ty, res) = self.lower_ty_ext(type_ref); return self.lower_ty_relative_path(ty, res, path.segments()); } + let (resolution, remaining_index) = match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path.mod_path()) { Some(it) => it, None => return (TyKind::Error.intern(Interner), None), }; + + if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() { + // trait object type without dyn + let bound = TypeBound::Path(path.clone(), TraitBoundModifier::None); + let ty = self.lower_dyn_trait(&[Interned::new(bound)]); + return (ty, None); + } + let (resolved_segment, remaining_segments) = match remaining_index { None => ( path.segments().last().expect("resolved path has at least one element"), @@ -987,6 +966,18 @@ impl<'a> TyLoweringContext<'a> { }) } + fn lower_dyn_trait(&self, bounds: &[Interned]) -> Ty { + let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner); + let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { + QuantifiedWhereClauses::from_iter( + Interner, + bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)), + ) + }); + let bounds = crate::make_single_type_binders(bounds); + TyKind::Dyn(DynTy { bounds, lifetime: static_lifetime() }).intern(Interner) + } + fn lower_impl_trait( &self, bounds: &[Interned], diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs index 75802a5eb4d..c128a051f72 100644 --- a/crates/hir-ty/src/tests/traits.rs +++ b/crates/hir-ty/src/tests/traits.rs @@ -1476,6 +1476,34 @@ fn test(x: Trait, y: &Trait) -> u64 { 165..172 'z.foo()': u64 "#]], ); + + check_infer_with_mismatches( + r#" +//- minicore: fn, coerce_unsized +struct S; +impl S { + fn foo(&self) {} +} +fn f(_: &Fn(S)) {} +fn main() { + f(&|number| number.foo()); +} + "#, + expect![[r#" + 31..35 'self': &S + 37..39 '{}': () + 47..48 '_': &dyn Fn(S) + 58..60 '{}': () + 71..105 '{ ...()); }': () + 77..78 'f': fn f(&dyn Fn(S)) + 77..102 'f(&|nu...foo())': () + 79..101 '&|numb....foo()': &|S| -> () + 80..101 '|numbe....foo()': |S| -> () + 81..87 'number': S + 89..95 'number': S + 89..101 'number.foo()': () + "#]], + ) } #[test] -- cgit 1.4.1-3-g733a5 From 83f081fc01f3173ef17a04da3cde313fa06d8502 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 15 Aug 2022 11:11:56 -0700 Subject: Remove unstable Result::into_ok_or_err --- .../0024-core-Disable-portable-simd-test.patch | 1 - compiler/rustc_transmute/src/layout/tree.rs | 13 +++++---- compiler/rustc_transmute/src/lib.rs | 9 +----- library/core/src/result.rs | 34 ---------------------- library/core/tests/lib.rs | 1 - library/core/tests/result.rs | 9 ------ 6 files changed, 8 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch b/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch index d5fa1cec061..c59a40df039 100644 --- a/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch +++ b/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch @@ -14,7 +14,6 @@ index 06c7be0..359e2e7 100644 @@ -75,7 +75,6 @@ #![feature(never_type)] #![feature(unwrap_infallible)] - #![feature(result_into_ok_or_err)] -#![feature(portable_simd)] #![feature(ptr_metadata)] #![feature(once_cell)] diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index 70b3ba02b05..402d2c95f5f 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -86,17 +86,18 @@ where F: Fn(D) -> bool, { match self { - Self::Seq(elts) => elts - .into_iter() - .map(|elt| elt.prune(f)) - .try_fold(Tree::unit(), |elts, elt| { + Self::Seq(elts) => match elts.into_iter().map(|elt| elt.prune(f)).try_fold( + Tree::unit(), + |elts, elt| { if elt == Tree::uninhabited() { Err(Tree::uninhabited()) } else { Ok(elts.then(elt)) } - }) - .into_ok_or_err(), + }, + ) { + Err(node) | Ok(node) => node, + }, Self::Alt(alts) => alts .into_iter() .map(|alt| alt.prune(f)) diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index cfc7c752a6b..01c50fb7cc8 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -1,11 +1,4 @@ -#![feature( - alloc_layout_extra, - control_flow_enum, - decl_macro, - iterator_try_reduce, - never_type, - result_into_ok_or_err -)] +#![feature(alloc_layout_extra, control_flow_enum, decl_macro, iterator_try_reduce, never_type)] #![allow(dead_code, unused_variables)] #[macro_use] diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 45b052c824d..6d583e28404 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1771,40 +1771,6 @@ impl Result, E> { } } -impl Result { - /// Returns the [`Ok`] value if `self` is `Ok`, and the [`Err`] value if - /// `self` is `Err`. - /// - /// In other words, this function returns the value (the `T`) of a - /// `Result`, regardless of whether or not that result is `Ok` or - /// `Err`. - /// - /// This can be useful in conjunction with APIs such as - /// [`Atomic*::compare_exchange`], or [`slice::binary_search`], but only in - /// cases where you don't care if the result was `Ok` or not. - /// - /// [`Atomic*::compare_exchange`]: crate::sync::atomic::AtomicBool::compare_exchange - /// - /// # Examples - /// - /// ``` - /// #![feature(result_into_ok_or_err)] - /// let ok: Result = Ok(3); - /// let err: Result = Err(4); - /// - /// assert_eq!(ok.into_ok_or_err(), 3); - /// assert_eq!(err.into_ok_or_err(), 4); - /// ``` - #[inline] - #[unstable(feature = "result_into_ok_or_err", reason = "newly added", issue = "82223")] - pub const fn into_ok_or_err(self) -> T { - match self { - Ok(v) => v, - Err(v) => v, - } - } -} - // This is a separate function to reduce the code size of the methods #[cfg(not(feature = "panic_immediate_abort"))] #[inline(never)] diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 09f1500f564..fe875c05aad 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -75,7 +75,6 @@ #![feature(const_pin)] #![feature(never_type)] #![feature(unwrap_infallible)] -#![feature(result_into_ok_or_err)] #![feature(pointer_byte_offsets)] #![feature(portable_simd)] #![feature(ptr_metadata)] diff --git a/library/core/tests/result.rs b/library/core/tests/result.rs index 103e8cc3a96..50926da3ce7 100644 --- a/library/core/tests/result.rs +++ b/library/core/tests/result.rs @@ -95,15 +95,6 @@ fn test_unwrap_or() { assert_eq!(ok_err.unwrap_or(50), 50); } -#[test] -fn test_ok_or_err() { - let ok: Result = Ok(100); - let err: Result = Err(200); - - assert_eq!(ok.into_ok_or_err(), 100); - assert_eq!(err.into_ok_or_err(), 200); -} - #[test] fn test_unwrap_or_else() { fn handler(msg: &'static str) -> isize { -- cgit 1.4.1-3-g733a5 From 39809c5f68e5618dc4183cfa95499df70357e617 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 15 Aug 2022 16:21:39 -0700 Subject: Replace a try_fold in rustc_transmute to use ControlFlow instead of Result --- compiler/rustc_transmute/src/layout/tree.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index 402d2c95f5f..93cab7ca533 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -1,4 +1,5 @@ use super::{Byte, Def, Ref}; +use std::ops::ControlFlow; #[cfg(test)] mod tests; @@ -90,13 +91,13 @@ where Tree::unit(), |elts, elt| { if elt == Tree::uninhabited() { - Err(Tree::uninhabited()) + ControlFlow::Break(Tree::uninhabited()) } else { - Ok(elts.then(elt)) + ControlFlow::Continue(elts.then(elt)) } }, ) { - Err(node) | Ok(node) => node, + ControlFlow::Break(node) | ControlFlow::Continue(node) => node, }, Self::Alt(alts) => alts .into_iter() -- cgit 1.4.1-3-g733a5 From c4a5b142113ce9d161fcb653fcb3ec11c45680bf Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 18 Aug 2022 01:12:46 +0000 Subject: Avoid overflow in is_impossible_method --- compiler/rustc_trait_selection/src/traits/mod.rs | 13 ++++++++++--- src/test/rustdoc/issue-100620.rs | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 src/test/rustdoc/issue-100620.rs diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index b6d6df1eec6..20e9cbaa38f 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -571,9 +571,16 @@ fn is_impossible_method<'tcx>( }); tcx.infer_ctxt().ignoring_regions().enter(|ref infcx| { - let mut fulfill_ctxt = >::new(tcx); - fulfill_ctxt.register_predicate_obligations(infcx, predicates_for_trait); - !fulfill_ctxt.select_all_or_error(infcx).is_empty() + for obligation in predicates_for_trait { + // Ignore overflow error, to be conservative. + if let Ok(result) = infcx.evaluate_obligation(&obligation) + && !result.may_apply() + { + return true; + } + } + + false }) } diff --git a/src/test/rustdoc/issue-100620.rs b/src/test/rustdoc/issue-100620.rs new file mode 100644 index 00000000000..097666eb515 --- /dev/null +++ b/src/test/rustdoc/issue-100620.rs @@ -0,0 +1,19 @@ +pub trait Bar {} + +pub trait Qux {} + +pub trait Foo { + fn bar() + where + T: Bar, + { + } +} + +pub struct Concrete; + +impl Foo<(), S> for Concrete {} + +impl Bar for T where S: Qux {} + +impl Qux for S where T: Bar {} -- cgit 1.4.1-3-g733a5 From b631ca0c2fbc69ce7718b50ff34a7c238f28c05f Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Thu, 18 Aug 2022 07:34:25 +0100 Subject: Windows: Load synch functions together Attempt to load all the required sync functions and fail if any one of them fails. This reintroduces a macro for optional loading of functions but keeps it separate from the fallback macro rather than having that do two different jobs. --- library/std/src/sys/windows/c.rs | 26 +++--- library/std/src/sys/windows/compat.rs | 120 ++++++++++++++++----------- library/std/src/sys/windows/thread_parker.rs | 27 +++--- 3 files changed, 94 insertions(+), 79 deletions(-) diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index c5a30f8bac8..ef3f6a9ba17 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -228,6 +228,8 @@ pub const IPV6_ADD_MEMBERSHIP: c_int = 12; pub const IPV6_DROP_MEMBERSHIP: c_int = 13; pub const MSG_PEEK: c_int = 0x2; +pub const LOAD_LIBRARY_SEARCH_SYSTEM32: u32 = 0x800; + #[repr(C)] #[derive(Copy, Clone)] pub struct linger { @@ -1030,6 +1032,7 @@ extern "system" { pub fn GetProcAddress(handle: HMODULE, name: LPCSTR) -> *mut c_void; pub fn GetModuleHandleA(lpModuleName: LPCSTR) -> HMODULE; pub fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE; + pub fn LoadLibraryExA(lplibfilename: *const i8, hfile: HANDLE, dwflags: u32) -> HINSTANCE; pub fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: LPFILETIME); pub fn GetSystemInfo(lpSystemInfo: LPSYSTEM_INFO); @@ -1250,21 +1253,16 @@ compat_fn_with_fallback! { } } -compat_fn_with_fallback! { - pub static SYNCH_API: &CStr = ansi_str!("api-ms-win-core-synch-l1-2-0"); - #[allow(unused)] - fn WakeByAddressSingle(Address: LPVOID) -> () { - // This fallback is currently tightly coupled to its use in Parker::unpark. - // - // FIXME: If `WakeByAddressSingle` needs to be used anywhere other than - // Parker::unpark then this fallback will be wrong and will need to be decoupled. - crate::sys::windows::thread_parker::unpark_keyed_event(Address) - } +compat_fn_optional! { + crate::sys::compat::load_synch_functions(); + pub fn WaitOnAddress( + Address: LPVOID, + CompareAddress: LPVOID, + AddressSize: SIZE_T, + dwMilliseconds: DWORD + ); + pub fn WakeByAddressSingle(Address: LPVOID); } -pub use crate::sys::compat::WaitOnAddress; -// Change exported name of `WakeByAddressSingle` to make the strange fallback -// behaviour clear. -pub use WakeByAddressSingle::call as wake_by_address_single_or_unpark_keyed_event; compat_fn_with_fallback! { pub static NTDLL: &CStr = ansi_str!("ntdll"); diff --git a/library/std/src/sys/windows/compat.rs b/library/std/src/sys/windows/compat.rs index 473544c4d4f..60cc705cef2 100644 --- a/library/std/src/sys/windows/compat.rs +++ b/library/std/src/sys/windows/compat.rs @@ -21,6 +21,7 @@ use crate::ffi::{c_void, CStr}; use crate::ptr::NonNull; +use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sys::c; /// Helper macro for creating CStrs from literals and symbol names. @@ -74,6 +75,20 @@ impl Module { NonNull::new(module).map(Self) } + /// Load the library (if not already loaded) + /// + /// # Safety + /// + /// The module must not be unloaded. + pub unsafe fn load_system_library(name: &CStr) -> Option { + let module = c::LoadLibraryExA( + name.as_ptr(), + crate::ptr::null_mut(), + c::LOAD_LIBRARY_SEARCH_SYSTEM32, + ); + NonNull::new(module).map(Self) + } + // Try to get the address of a function. pub fn proc_address(self, name: &CStr) -> Option> { // SAFETY: @@ -144,61 +159,66 @@ macro_rules! compat_fn_with_fallback { )*) } -/// Optionally load `WaitOnAddress`. -/// Unlike the dynamic loading described above, this does not have a fallback. +/// Optionally loaded functions. /// -/// This is rexported from sys::c. You should prefer to import -/// from there in case this changes again in the future. -pub mod WaitOnAddress { - use super::*; - use crate::mem; - use crate::ptr; - use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering}; - use crate::sys::c; - - static MODULE_NAME: &CStr = ansi_str!("api-ms-win-core-synch-l1-2-0"); - static SYMBOL_NAME: &CStr = ansi_str!("WaitOnAddress"); - - // WaitOnAddress function signature. - type F = unsafe extern "system" fn( - Address: c::LPVOID, - CompareAddress: c::LPVOID, - AddressSize: c::SIZE_T, - dwMilliseconds: c::DWORD, - ); - - // A place to store the loaded function atomically. - static WAIT_ON_ADDRESS: AtomicPtr = AtomicPtr::new(ptr::null_mut()); - - // We can skip trying to load again if we already tried. - static LOAD_MODULE: AtomicBool = AtomicBool::new(true); +/// Actual loading of the function defers to $load_functions. +macro_rules! compat_fn_optional { + ($load_functions:expr; + $( + $(#[$meta:meta])* + $vis:vis fn $symbol:ident($($argname:ident: $argtype:ty),*) $(-> $rettype:ty)?; + )+) => ( + $( + pub mod $symbol { + use super::*; + use crate::ffi::c_void; + use crate::mem; + use crate::ptr::{self, NonNull}; + use crate::sync::atomic::{AtomicPtr, Ordering}; + + pub(in crate::sys) static PTR: AtomicPtr = AtomicPtr::new(ptr::null_mut()); + + type F = unsafe extern "system" fn($($argtype),*) $(-> $rettype)?; + + #[inline(always)] + pub fn option() -> Option { + let f = PTR.load(Ordering::Acquire); + if !f.is_null() { Some(unsafe { mem::transmute(f) }) } else { try_load() } + } - #[inline(always)] - pub fn option() -> Option { - let f = WAIT_ON_ADDRESS.load(Ordering::Acquire); - if !f.is_null() { Some(unsafe { mem::transmute(f) }) } else { try_load() } + #[cold] + fn try_load() -> Option { + $load_functions; + NonNull::new(PTR.load(Ordering::Acquire)).map(|f| unsafe { mem::transmute(f) }) + } + } + )+ + ) +} + +/// Load all needed functions from "api-ms-win-core-synch-l1-2-0". +pub(super) fn load_synch_functions() { + fn try_load() -> Option<()> { + static MODULE_NAME: &CStr = ansi_str!("api-ms-win-core-synch-l1-2-0"); + static WAIT_ON_ADDRESS: &CStr = ansi_str!("WaitOnAddress"); + static WAKE_BY_ADDRESS_SINGLE: &CStr = ansi_str!("WakeByAddressSingle"); + + // Try loading the library and all the required functions. + // If any step fails, then they all fail. + let library = unsafe { Module::load_system_library(MODULE_NAME) }?; + let wait_on_address = library.proc_address(WAIT_ON_ADDRESS)?; + let wake_by_address_single = library.proc_address(WAKE_BY_ADDRESS_SINGLE)?; + + c::WaitOnAddress::PTR.store(wait_on_address.as_ptr(), Ordering::Release); + c::WakeByAddressSingle::PTR.store(wake_by_address_single.as_ptr(), Ordering::Release); + Some(()) } - #[cold] - fn try_load() -> Option { - if LOAD_MODULE.load(Ordering::Acquire) { - // load the module - let mut wait_on_address = None; - if let Some(func) = try_load_inner() { - WAIT_ON_ADDRESS.store(func.as_ptr(), Ordering::Release); - wait_on_address = Some(unsafe { mem::transmute(func) }); - } - // Don't try to load the module again even if loading failed. + // Shortcut if we've already tried (and failed) to load the library. + static LOAD_MODULE: AtomicBool = AtomicBool::new(true); + if LOAD_MODULE.load(Ordering::Acquire) { + if try_load().is_none() { LOAD_MODULE.store(false, Ordering::Release); - wait_on_address - } else { - None } } - - // In the future this could be a `try` block but until then I think it's a - // little bit cleaner as a separate function. - fn try_load_inner() -> Option> { - unsafe { Module::new(MODULE_NAME)?.proc_address(SYMBOL_NAME) } - } } diff --git a/library/std/src/sys/windows/thread_parker.rs b/library/std/src/sys/windows/thread_parker.rs index 16863c9903a..2f7ae863b6a 100644 --- a/library/std/src/sys/windows/thread_parker.rs +++ b/library/std/src/sys/windows/thread_parker.rs @@ -198,8 +198,18 @@ impl Parker { // with park(). if self.state.swap(NOTIFIED, Release) == PARKED { unsafe { - // This calls either WakeByAddressSingle or unpark_keyed_event (see below). - c::wake_by_address_single_or_unpark_keyed_event(self.ptr()); + if let Some(wake_by_address_single) = c::WakeByAddressSingle::option() { + wake_by_address_single(self.ptr()); + } else { + // If we run NtReleaseKeyedEvent before the waiting thread runs + // NtWaitForKeyedEvent, this (shortly) blocks until we can wake it up. + // If the waiting thread wakes up before we run NtReleaseKeyedEvent + // (e.g. due to a timeout), this blocks until we do wake up a thread. + // To prevent this thread from blocking indefinitely in that case, + // park_impl() will, after seeing the state set to NOTIFIED after + // waking up, call NtWaitForKeyedEvent again to unblock us. + c::NtReleaseKeyedEvent(keyed_event_handle(), self.ptr(), 0, ptr::null_mut()); + } } } } @@ -209,19 +219,6 @@ impl Parker { } } -// This function signature makes it compatible with c::WakeByAddressSingle -// so that it can be used as a fallback for that function. -pub unsafe extern "C" fn unpark_keyed_event(address: c::LPVOID) { - // If we run NtReleaseKeyedEvent before the waiting thread runs - // NtWaitForKeyedEvent, this (shortly) blocks until we can wake it up. - // If the waiting thread wakes up before we run NtReleaseKeyedEvent - // (e.g. due to a timeout), this blocks until we do wake up a thread. - // To prevent this thread from blocking indefinitely in that case, - // park_impl() will, after seeing the state set to NOTIFIED after - // waking up, call NtWaitForKeyedEvent again to unblock us. - c::NtReleaseKeyedEvent(keyed_event_handle(), address, 0, ptr::null_mut()); -} - fn keyed_event_handle() -> c::HANDLE { const INVALID: c::HANDLE = ptr::invalid_mut(!0); static HANDLE: AtomicPtr = AtomicPtr::new(INVALID); -- cgit 1.4.1-3-g733a5 From 57c85bd97da336a2199d1b157fb18e70efcafd35 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 17 Aug 2022 12:55:00 +0200 Subject: Remove need to give JSON file path --- src/tools/jsondocck/src/cache.rs | 70 ++++++------------------------- src/tools/jsondocck/src/main.rs | 90 ++++++++++++++++++---------------------- 2 files changed, 53 insertions(+), 107 deletions(-) diff --git a/src/tools/jsondocck/src/cache.rs b/src/tools/jsondocck/src/cache.rs index a188750c56a..f9e54232750 100644 --- a/src/tools/jsondocck/src/cache.rs +++ b/src/tools/jsondocck/src/cache.rs @@ -1,77 +1,31 @@ -use crate::error::CkError; +use crate::config::Config; use serde_json::Value; use std::collections::HashMap; -use std::io; -use std::path::{Path, PathBuf}; +use std::path::Path; use fs_err as fs; #[derive(Debug)] pub struct Cache { - root: PathBuf, - files: HashMap, - values: HashMap, + value: Value, pub variables: HashMap, - last_path: Option, } impl Cache { /// Create a new cache, used to read files only once and otherwise store their contents. - pub fn new(doc_dir: &str) -> Cache { + pub fn new(config: &Config) -> Cache { + let root = Path::new(&config.doc_dir); + let filename = Path::new(&config.template).file_stem().unwrap(); + let file_path = root.join(&Path::with_extension(Path::new(filename), "json")); + let content = fs::read_to_string(&file_path).expect("failed to read JSON file"); + Cache { - root: Path::new(doc_dir).to_owned(), - files: HashMap::new(), - values: HashMap::new(), + value: serde_json::from_str::(&content).expect("failed to convert from JSON"), variables: HashMap::new(), - last_path: None, } } - fn resolve_path(&mut self, path: &String) -> PathBuf { - if path != "-" { - let resolve = self.root.join(path); - self.last_path = Some(resolve.clone()); - resolve - } else { - self.last_path - .as_ref() - // FIXME: Point to a line number - .expect("No last path set. Make sure to specify a full path before using `-`") - .clone() - } - } - - fn read_file(&mut self, path: PathBuf) -> Result { - if let Some(f) = self.files.get(&path) { - return Ok(f.clone()); - } - - let file = fs::read_to_string(&path)?; - - self.files.insert(path, file.clone()); - - Ok(file) - } - - /// Get the text from a file. If called multiple times, the file will only be read once - pub fn get_file(&mut self, path: &String) -> Result { - let path = self.resolve_path(path); - self.read_file(path) - } - - /// Parse the JSON from a file. If called multiple times, the file will only be read once. - pub fn get_value(&mut self, path: &String) -> Result { - let path = self.resolve_path(path); - - if let Some(v) = self.values.get(&path) { - return Ok(v.clone()); - } - - let content = self.read_file(path.clone())?; - let val = serde_json::from_str::(&content)?; - - self.values.insert(path, val.clone()); - - Ok(val) + pub fn value(&self) -> &Value { + &self.value } } diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs index 022f7eb8e02..76770fe36a7 100644 --- a/src/tools/jsondocck/src/main.rs +++ b/src/tools/jsondocck/src/main.rs @@ -17,7 +17,7 @@ fn main() -> Result<(), String> { let config = parse_config(env::args().collect()); let mut failed = Vec::new(); - let mut cache = Cache::new(&config.doc_dir); + let mut cache = Cache::new(&config); let commands = get_commands(&config.template) .map_err(|_| format!("Jsondocck failed for {}", &config.template))?; @@ -55,12 +55,12 @@ pub enum CommandKind { } impl CommandKind { - fn validate(&self, args: &[String], command_num: usize, lineno: usize) -> bool { + fn validate(&self, args: &[String], lineno: usize) -> bool { let count = match self { - CommandKind::Has => (1..=3).contains(&args.len()), - CommandKind::IsMany => args.len() >= 3, - CommandKind::Count | CommandKind::Is => 3 == args.len(), - CommandKind::Set => 4 == args.len(), + CommandKind::Has => (1..=2).contains(&args.len()), + CommandKind::IsMany => args.len() >= 2, + CommandKind::Count | CommandKind::Is => 2 == args.len(), + CommandKind::Set => 3 == args.len(), }; if !count { @@ -68,15 +68,10 @@ impl CommandKind { return false; } - if args[0] == "-" && command_num == 0 { - print_err(&format!("Tried to use the previous path in the first command"), lineno); - return false; - } - if let CommandKind::Count = self { - if args[2].parse::().is_err() { + if args[1].parse::().is_err() { print_err( - &format!("Third argument to @count must be a valid usize (got `{}`)", args[2]), + &format!("Second argument to @count must be a valid usize (got `{}`)", args[2]), lineno, ); return false; @@ -181,7 +176,7 @@ fn get_commands(template: &str) -> Result, ()> { } }; - if !cmd.validate(&args, commands.len(), lineno) { + if !cmd.validate(&args, lineno) { errors = true; continue; } @@ -199,26 +194,24 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> { let result = match command.kind { CommandKind::Has => { match command.args.len() { - // @has = file existence - 1 => cache.get_file(&command.args[0]).is_ok(), - // @has = check path exists - 2 => { - let val = cache.get_value(&command.args[0])?; - let results = select(&val, &command.args[1]).unwrap(); + // @has = check path exists + 1 => { + let val = cache.value(); + let results = select(val, &command.args[0]).unwrap(); !results.is_empty() } - // @has = check *any* item matched by path equals value - 3 => { - let val = cache.get_value(&command.args[0])?; - let results = select(&val, &command.args[1]).unwrap(); - let pat = string_to_value(&command.args[2], cache); + // @has = check *any* item matched by path equals value + 2 => { + let val = cache.value().clone(); + let results = select(&val, &command.args[0]).unwrap(); + let pat = string_to_value(&command.args[1], cache); let has = results.contains(&pat.as_ref()); // Give better error for when @has check fails if !command.negated && !has { return Err(CkError::FailedCheck( format!( "{} matched to {:?} but didn't have {:?}", - &command.args[1], + &command.args[0], results, pat.as_ref() ), @@ -233,13 +226,13 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> { } CommandKind::IsMany => { // @ismany ... - let (path, query, values) = if let [path, query, values @ ..] = &command.args[..] { - (path, query, values) + let (query, values) = if let [query, values @ ..] = &command.args[..] { + (query, values) } else { unreachable!("Checked in CommandKind::validate") }; - let val = cache.get_value(path)?; - let got_values = select(&val, &query).unwrap(); + let val = cache.value(); + let got_values = select(val, &query).unwrap(); assert!(!command.negated, "`@!ismany` is not supported"); // Serde json doesn't implement Ord or Hash for Value, so we must @@ -270,18 +263,17 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> { true } CommandKind::Count => { - // @count = Check that the jsonpath matches exactly [count] times - assert_eq!(command.args.len(), 3); - let expected: usize = command.args[2].parse().unwrap(); - - let val = cache.get_value(&command.args[0])?; - let results = select(&val, &command.args[1]).unwrap(); + // @count = Check that the jsonpath matches exactly [count] times + assert_eq!(command.args.len(), 2); + let expected: usize = command.args[1].parse().unwrap(); + let val = cache.value(); + let results = select(val, &command.args[0]).unwrap(); let eq = results.len() == expected; if !command.negated && !eq { return Err(CkError::FailedCheck( format!( "`{}` matched to `{:?}` with length {}, but expected length {}", - &command.args[1], + &command.args[0], results, results.len(), expected @@ -293,17 +285,17 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> { } } CommandKind::Is => { - // @has = check *exactly one* item matched by path, and it equals value - assert_eq!(command.args.len(), 3); - let val = cache.get_value(&command.args[0])?; - let results = select(&val, &command.args[1]).unwrap(); - let pat = string_to_value(&command.args[2], cache); + // @has = check *exactly one* item matched by path, and it equals value + assert_eq!(command.args.len(), 2); + let val = cache.value().clone(); + let results = select(&val, &command.args[0]).unwrap(); + let pat = string_to_value(&command.args[1], cache); let is = results.len() == 1 && results[0] == pat.as_ref(); if !command.negated && !is { return Err(CkError::FailedCheck( format!( "{} matched to {:?}, but expected {:?}", - &command.args[1], + &command.args[0], results, pat.as_ref() ), @@ -314,16 +306,16 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> { } } CommandKind::Set => { - // @set = - assert_eq!(command.args.len(), 4); + // @set = + assert_eq!(command.args.len(), 3); assert_eq!(command.args[1], "=", "Expected an `=`"); - let val = cache.get_value(&command.args[2])?; - let results = select(&val, &command.args[3]).unwrap(); + let val = cache.value().clone(); + let results = select(&val, &command.args[2]).unwrap(); assert_eq!( results.len(), 1, "Expected 1 match for `{}` (because of @set): matched to {:?}", - command.args[3], + command.args[2], results ); match results.len() { @@ -336,7 +328,7 @@ fn check_command(command: Command, cache: &mut Cache) -> Result<(), CkError> { _ => { panic!( "Got multiple results in `@set` for `{}`: {:?}", - &command.args[3], results + &command.args[2], results, ); } } -- cgit 1.4.1-3-g733a5 From d3d9e223e2d9d12ca68e48b5d1e0adf96793cca7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 17 Aug 2022 12:55:09 +0200 Subject: Update rustdoc-json test files --- src/test/rustdoc-json/assoc_items.rs | 22 +++-- src/test/rustdoc-json/assoc_type.rs | 9 +- src/test/rustdoc-json/blanket_impls.rs | 7 +- src/test/rustdoc-json/doc_hidden_failure.rs | 2 +- src/test/rustdoc-json/enum_variant_hidden.rs | 8 +- src/test/rustdoc-json/enums/variant_struct.rs | 10 +-- .../rustdoc-json/enums/variant_tuple_struct.rs | 10 +-- src/test/rustdoc-json/fn_pointer/abi.rs | 14 ++-- src/test/rustdoc-json/fn_pointer/generics.rs | 16 ++-- src/test/rustdoc-json/fn_pointer/qualifiers.rs | 12 +-- src/test/rustdoc-json/fns/abi.rs | 14 ++-- src/test/rustdoc-json/fns/generic_args.rs | 96 +++++++++++----------- src/test/rustdoc-json/fns/generic_returns.rs | 12 +-- src/test/rustdoc-json/fns/generics.rs | 32 ++++---- src/test/rustdoc-json/fns/qualifiers.rs | 36 ++++---- .../rustdoc-json/generic-associated-types/gats.rs | 40 +++++---- src/test/rustdoc-json/generic_impl.rs | 7 +- src/test/rustdoc-json/glob_import.rs | 5 +- src/test/rustdoc-json/impls/auto.rs | 6 +- src/test/rustdoc-json/impls/blanket_with_local.rs | 8 +- src/test/rustdoc-json/impls/import_from_private.rs | 16 ++-- src/test/rustdoc-json/keyword.rs | 9 +- src/test/rustdoc-json/lifetime/longest.rs | 40 ++++----- src/test/rustdoc-json/lifetime/outlives.rs | 34 ++++---- src/test/rustdoc-json/methods/abi.rs | 30 +++---- src/test/rustdoc-json/methods/qualifiers.rs | 36 ++++---- src/test/rustdoc-json/nested.rs | 38 ++++----- src/test/rustdoc-json/output_generics.rs | 11 ++- src/test/rustdoc-json/primitive.rs | 16 ++-- src/test/rustdoc-json/primitive_overloading.rs | 5 +- src/test/rustdoc-json/primitives.rs | 22 ++--- .../reexport/export_extern_crate_as_self.rs | 2 +- src/test/rustdoc-json/reexport/glob_extern.rs | 20 ++--- src/test/rustdoc-json/reexport/glob_private.rs | 26 +++--- src/test/rustdoc-json/reexport/in_root_and_mod.rs | 10 +-- .../rustdoc-json/reexport/in_root_and_mod_pub.rs | 16 ++-- src/test/rustdoc-json/reexport/macro.rs | 6 +- .../reexport/private_twice_one_inline.rs | 16 ++-- .../rustdoc-json/reexport/private_two_names.rs | 16 ++-- src/test/rustdoc-json/reexport/rename_private.rs | 8 +- src/test/rustdoc-json/reexport/rename_public.rs | 14 ++-- .../same_type_reexported_more_than_once.rs | 14 ++-- src/test/rustdoc-json/reexport/simple_private.rs | 14 ++-- src/test/rustdoc-json/reexport/simple_public.rs | 12 +-- src/test/rustdoc-json/return_private.rs | 4 +- src/test/rustdoc-json/stripped_modules.rs | 10 +-- src/test/rustdoc-json/structs/plain_empty.rs | 10 +-- src/test/rustdoc-json/structs/tuple.rs | 8 +- src/test/rustdoc-json/structs/unit.rs | 8 +- src/test/rustdoc-json/structs/with_generics.rs | 16 ++-- src/test/rustdoc-json/structs/with_primitives.rs | 12 +-- src/test/rustdoc-json/traits/has_body.rs | 16 ++-- src/test/rustdoc-json/traits/implementors.rs | 14 ++-- src/test/rustdoc-json/traits/supertrait.rs | 22 ++--- src/test/rustdoc-json/type/dyn.rs | 78 +++++++++--------- src/test/rustdoc-json/type/fn_lifetime.rs | 40 ++++----- src/test/rustdoc-json/type/generic_default.rs | 46 +++++------ src/test/rustdoc-json/type/hrtb.rs | 22 +++-- src/test/rustdoc-json/unions/impl.rs | 10 +-- src/test/rustdoc-json/unions/union.rs | 6 +- 60 files changed, 552 insertions(+), 567 deletions(-) diff --git a/src/test/rustdoc-json/assoc_items.rs b/src/test/rustdoc-json/assoc_items.rs index 2ee64c9f6eb..2eb413fb402 100644 --- a/src/test/rustdoc-json/assoc_items.rs +++ b/src/test/rustdoc-json/assoc_items.rs @@ -1,29 +1,27 @@ #![no_std] -// @has assoc_items.json - pub struct Simple; impl Simple { - // @has - "$.index[*][?(@.name=='CONSTANT')].kind" \"assoc_const\" + // @has "$.index[*][?(@.name=='CONSTANT')].kind" \"assoc_const\" pub const CONSTANT: usize = 0; } pub trait EasyToImpl { - // @has - "$.index[*][?(@.name=='ToDeclare')].kind" \"assoc_type\" - // @has - "$.index[*][?(@.name=='ToDeclare')].inner.default" null + // @has "$.index[*][?(@.name=='ToDeclare')].kind" \"assoc_type\" + // @has "$.index[*][?(@.name=='ToDeclare')].inner.default" null type ToDeclare; - // @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].kind" \"assoc_const\" - // @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.default" null + // @has "$.index[*][?(@.name=='AN_ATTRIBUTE')].kind" \"assoc_const\" + // @has "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.default" null const AN_ATTRIBUTE: usize; } impl EasyToImpl for Simple { - // @has - "$.index[*][?(@.name=='ToDeclare')].inner.default.kind" \"primitive\" - // @has - "$.index[*][?(@.name=='ToDeclare')].inner.default.inner" \"usize\" + // @has "$.index[*][?(@.name=='ToDeclare')].inner.default.kind" \"primitive\" + // @has "$.index[*][?(@.name=='ToDeclare')].inner.default.inner" \"usize\" type ToDeclare = usize; - // @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.type.kind" \"primitive\" - // @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.type.inner" \"usize\" - // @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.default" \"12\" + // @has "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.type.kind" \"primitive\" + // @has "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.type.inner" \"usize\" + // @has "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.default" \"12\" const AN_ATTRIBUTE: usize = 12; } diff --git a/src/test/rustdoc-json/assoc_type.rs b/src/test/rustdoc-json/assoc_type.rs index 716bb3d2848..edc1f73c866 100644 --- a/src/test/rustdoc-json/assoc_type.rs +++ b/src/test/rustdoc-json/assoc_type.rs @@ -1,10 +1,9 @@ // Regression test for . -// @has assoc_type.json -// @has - "$.index[*][?(@.name=='Trait')]" -// @has - "$.index[*][?(@.name=='AssocType')]" -// @has - "$.index[*][?(@.name=='S')]" -// @has - "$.index[*][?(@.name=='S2')]" +// @has "$.index[*][?(@.name=='Trait')]" +// @has "$.index[*][?(@.name=='AssocType')]" +// @has "$.index[*][?(@.name=='S')]" +// @has "$.index[*][?(@.name=='S2')]" pub trait Trait { type AssocType; diff --git a/src/test/rustdoc-json/blanket_impls.rs b/src/test/rustdoc-json/blanket_impls.rs index edf1a9fe2fc..c5cc87ca1eb 100644 --- a/src/test/rustdoc-json/blanket_impls.rs +++ b/src/test/rustdoc-json/blanket_impls.rs @@ -2,8 +2,7 @@ #![no_std] -// @has blanket_impls.json -// @has - "$.index[*][?(@.name=='Error')].kind" \"assoc_type\" -// @has - "$.index[*][?(@.name=='Error')].inner.default.kind" \"resolved_path\" -// @has - "$.index[*][?(@.name=='Error')].inner.default.inner.name" \"Infallible\" +// @has "$.index[*][?(@.name=='Error')].kind" \"assoc_type\" +// @has "$.index[*][?(@.name=='Error')].inner.default.kind" \"resolved_path\" +// @has "$.index[*][?(@.name=='Error')].inner.default.inner.name" \"Infallible\" pub struct ForBlanketTryFromImpl; diff --git a/src/test/rustdoc-json/doc_hidden_failure.rs b/src/test/rustdoc-json/doc_hidden_failure.rs index 5c4ccf996a5..6573166c47f 100644 --- a/src/test/rustdoc-json/doc_hidden_failure.rs +++ b/src/test/rustdoc-json/doc_hidden_failure.rs @@ -14,7 +14,7 @@ mod auto { } } -// @count doc_hidden_failure.json "$.index[*][?(@.name=='builders')]" 2 +// @count "$.index[*][?(@.name=='builders')]" 2 pub use auto::*; pub mod builders { diff --git a/src/test/rustdoc-json/enum_variant_hidden.rs b/src/test/rustdoc-json/enum_variant_hidden.rs index 96c96a975d3..c5e063a055c 100644 --- a/src/test/rustdoc-json/enum_variant_hidden.rs +++ b/src/test/rustdoc-json/enum_variant_hidden.rs @@ -3,10 +3,10 @@ #![no_core] #![feature(no_core)] -// @has enum_variant_hidden.json "$.index[*][?(@.name=='ParseError')]" -// @has - "$.index[*][?(@.name=='UnexpectedEndTag')]" -// @is - "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant_kind" '"tuple"' -// @is - "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant_inner" [] +// @has "$.index[*][?(@.name=='ParseError')]" +// @has "$.index[*][?(@.name=='UnexpectedEndTag')]" +// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant_kind" '"tuple"' +// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant_inner" [] pub enum ParseError { UnexpectedEndTag(#[doc(hidden)] u32), diff --git a/src/test/rustdoc-json/enums/variant_struct.rs b/src/test/rustdoc-json/enums/variant_struct.rs index fcd92887c0b..704ec35d2f0 100644 --- a/src/test/rustdoc-json/enums/variant_struct.rs +++ b/src/test/rustdoc-json/enums/variant_struct.rs @@ -1,9 +1,9 @@ -// @has variant_struct.json "$.index[*][?(@.name=='EnumStruct')].visibility" \"public\" -// @has - "$.index[*][?(@.name=='EnumStruct')].kind" \"enum\" +// @has "$.index[*][?(@.name=='EnumStruct')].visibility" \"public\" +// @has "$.index[*][?(@.name=='EnumStruct')].kind" \"enum\" pub enum EnumStruct { - // @has - "$.index[*][?(@.name=='VariantS')].inner.variant_kind" \"struct\" - // @has - "$.index[*][?(@.name=='x')].kind" \"struct_field\" - // @has - "$.index[*][?(@.name=='y')].kind" \"struct_field\" + // @has "$.index[*][?(@.name=='VariantS')].inner.variant_kind" \"struct\" + // @has "$.index[*][?(@.name=='x')].kind" \"struct_field\" + // @has "$.index[*][?(@.name=='y')].kind" \"struct_field\" VariantS { x: u32, y: String, diff --git a/src/test/rustdoc-json/enums/variant_tuple_struct.rs b/src/test/rustdoc-json/enums/variant_tuple_struct.rs index ac3e72e2905..71ddd73ec76 100644 --- a/src/test/rustdoc-json/enums/variant_tuple_struct.rs +++ b/src/test/rustdoc-json/enums/variant_tuple_struct.rs @@ -1,8 +1,8 @@ -// @has variant_tuple_struct.json "$.index[*][?(@.name=='EnumTupleStruct')].visibility" \"public\" -// @has - "$.index[*][?(@.name=='EnumTupleStruct')].kind" \"enum\" +// @has "$.index[*][?(@.name=='EnumTupleStruct')].visibility" \"public\" +// @has "$.index[*][?(@.name=='EnumTupleStruct')].kind" \"enum\" pub enum EnumTupleStruct { - // @has - "$.index[*][?(@.name=='VariantA')].inner.variant_kind" \"tuple\" - // @has - "$.index[*][?(@.name=='0')].kind" \"struct_field\" - // @has - "$.index[*][?(@.name=='1')].kind" \"struct_field\" + // @has "$.index[*][?(@.name=='VariantA')].inner.variant_kind" \"tuple\" + // @has "$.index[*][?(@.name=='0')].kind" \"struct_field\" + // @has "$.index[*][?(@.name=='1')].kind" \"struct_field\" VariantA(u32, String), } diff --git a/src/test/rustdoc-json/fn_pointer/abi.rs b/src/test/rustdoc-json/fn_pointer/abi.rs index eef20e60a6a..3c1a453d12d 100644 --- a/src/test/rustdoc-json/fn_pointer/abi.rs +++ b/src/test/rustdoc-json/fn_pointer/abi.rs @@ -3,23 +3,23 @@ #![feature(abi_vectorcall)] #![feature(c_unwind)] -// @is abi.json "$.index[*][?(@.name=='AbiRust')].inner.type.inner.header.abi" \"Rust\" +// @is "$.index[*][?(@.name=='AbiRust')].inner.type.inner.header.abi" \"Rust\" pub type AbiRust = fn(); -// @is - "$.index[*][?(@.name=='AbiC')].inner.type.inner.header.abi" '{"C": {"unwind": false}}' +// @is "$.index[*][?(@.name=='AbiC')].inner.type.inner.header.abi" '{"C": {"unwind": false}}' pub type AbiC = extern "C" fn(); -// @is - "$.index[*][?(@.name=='AbiSystem')].inner.type.inner.header.abi" '{"System": {"unwind": false}}' +// @is "$.index[*][?(@.name=='AbiSystem')].inner.type.inner.header.abi" '{"System": {"unwind": false}}' pub type AbiSystem = extern "system" fn(); -// @is - "$.index[*][?(@.name=='AbiCUnwind')].inner.type.inner.header.abi" '{"C": {"unwind": true}}' +// @is "$.index[*][?(@.name=='AbiCUnwind')].inner.type.inner.header.abi" '{"C": {"unwind": true}}' pub type AbiCUnwind = extern "C-unwind" fn(); -// @is - "$.index[*][?(@.name=='AbiSystemUnwind')].inner.type.inner.header.abi" '{"System": {"unwind": true}}' +// @is "$.index[*][?(@.name=='AbiSystemUnwind')].inner.type.inner.header.abi" '{"System": {"unwind": true}}' pub type AbiSystemUnwind = extern "system-unwind" fn(); -// @is - "$.index[*][?(@.name=='AbiVecorcall')].inner.type.inner.header.abi.Other" '"\"vectorcall\""' +// @is "$.index[*][?(@.name=='AbiVecorcall')].inner.type.inner.header.abi.Other" '"\"vectorcall\""' pub type AbiVecorcall = extern "vectorcall" fn(); -// @is - "$.index[*][?(@.name=='AbiVecorcallUnwind')].inner.type.inner.header.abi.Other" '"\"vectorcall-unwind\""' +// @is "$.index[*][?(@.name=='AbiVecorcallUnwind')].inner.type.inner.header.abi.Other" '"\"vectorcall-unwind\""' pub type AbiVecorcallUnwind = extern "vectorcall-unwind" fn(); diff --git a/src/test/rustdoc-json/fn_pointer/generics.rs b/src/test/rustdoc-json/fn_pointer/generics.rs index 646f720e663..a93b01ac2c4 100644 --- a/src/test/rustdoc-json/fn_pointer/generics.rs +++ b/src/test/rustdoc-json/fn_pointer/generics.rs @@ -3,12 +3,12 @@ #![feature(no_core)] #![no_core] -// @count generics.json "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[*]" 1 -// @is - "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[0][0]" '"val"' -// @is - "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[0][1].kind" '"borrowed_ref"' -// @is - "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[0][1].inner.lifetime" \"\'c\" -// @is - "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.output" '{ "kind": "primitive", "inner": "i32" }' -// @count - "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.generic_params[*]" 1 -// @is - "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.generic_params[0].name" \"\'c\" -// @is - "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }' +// @count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[*]" 1 +// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[0][0]" '"val"' +// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[0][1].kind" '"borrowed_ref"' +// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[0][1].inner.lifetime" \"\'c\" +// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.output" '{ "kind": "primitive", "inner": "i32" }' +// @count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.generic_params[*]" 1 +// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.generic_params[0].name" \"\'c\" +// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }' pub type WithHigherRankTraitBounds = for<'c> fn(val: &'c i32) -> i32; diff --git a/src/test/rustdoc-json/fn_pointer/qualifiers.rs b/src/test/rustdoc-json/fn_pointer/qualifiers.rs index 38192208536..bd65bb3eefe 100644 --- a/src/test/rustdoc-json/fn_pointer/qualifiers.rs +++ b/src/test/rustdoc-json/fn_pointer/qualifiers.rs @@ -1,9 +1,9 @@ -// @is qualifiers.json "$.index[*][?(@.name=='FnPointer')].inner.type.inner.header.unsafe" false -// @is - "$.index[*][?(@.name=='FnPointer')].inner.type.inner.header.const" false -// @is - "$.index[*][?(@.name=='FnPointer')].inner.type.inner.header.async" false +// @is "$.index[*][?(@.name=='FnPointer')].inner.type.inner.header.unsafe" false +// @is "$.index[*][?(@.name=='FnPointer')].inner.type.inner.header.const" false +// @is "$.index[*][?(@.name=='FnPointer')].inner.type.inner.header.async" false pub type FnPointer = fn(); -// @is - "$.index[*][?(@.name=='UnsafePointer')].inner.type.inner.header.unsafe" true -// @is - "$.index[*][?(@.name=='UnsafePointer')].inner.type.inner.header.const" false -// @is - "$.index[*][?(@.name=='UnsafePointer')].inner.type.inner.header.async" false +// @is "$.index[*][?(@.name=='UnsafePointer')].inner.type.inner.header.unsafe" true +// @is "$.index[*][?(@.name=='UnsafePointer')].inner.type.inner.header.const" false +// @is "$.index[*][?(@.name=='UnsafePointer')].inner.type.inner.header.async" false pub type UnsafePointer = unsafe fn(); diff --git a/src/test/rustdoc-json/fns/abi.rs b/src/test/rustdoc-json/fns/abi.rs index 16b57913065..0e8b78bc0e6 100644 --- a/src/test/rustdoc-json/fns/abi.rs +++ b/src/test/rustdoc-json/fns/abi.rs @@ -3,23 +3,23 @@ #![feature(abi_vectorcall)] #![feature(c_unwind)] -// @is abi.json "$.index[*][?(@.name=='abi_rust')].inner.header.abi" \"Rust\" +// @is "$.index[*][?(@.name=='abi_rust')].inner.header.abi" \"Rust\" pub fn abi_rust() {} -// @is - "$.index[*][?(@.name=='abi_c')].inner.header.abi" '{"C": {"unwind": false}}' +// @is "$.index[*][?(@.name=='abi_c')].inner.header.abi" '{"C": {"unwind": false}}' pub extern "C" fn abi_c() {} -// @is - "$.index[*][?(@.name=='abi_system')].inner.header.abi" '{"System": {"unwind": false}}' +// @is "$.index[*][?(@.name=='abi_system')].inner.header.abi" '{"System": {"unwind": false}}' pub extern "system" fn abi_system() {} -// @is - "$.index[*][?(@.name=='abi_c_unwind')].inner.header.abi" '{"C": {"unwind": true}}' +// @is "$.index[*][?(@.name=='abi_c_unwind')].inner.header.abi" '{"C": {"unwind": true}}' pub extern "C-unwind" fn abi_c_unwind() {} -// @is - "$.index[*][?(@.name=='abi_system_unwind')].inner.header.abi" '{"System": {"unwind": true}}' +// @is "$.index[*][?(@.name=='abi_system_unwind')].inner.header.abi" '{"System": {"unwind": true}}' pub extern "system-unwind" fn abi_system_unwind() {} -// @is - "$.index[*][?(@.name=='abi_vectorcall')].inner.header.abi.Other" '"\"vectorcall\""' +// @is "$.index[*][?(@.name=='abi_vectorcall')].inner.header.abi.Other" '"\"vectorcall\""' pub extern "vectorcall" fn abi_vectorcall() {} -// @is - "$.index[*][?(@.name=='abi_vectorcall_unwind')].inner.header.abi.Other" '"\"vectorcall-unwind\""' +// @is "$.index[*][?(@.name=='abi_vectorcall_unwind')].inner.header.abi.Other" '"\"vectorcall-unwind\""' pub extern "vectorcall-unwind" fn abi_vectorcall_unwind() {} diff --git a/src/test/rustdoc-json/fns/generic_args.rs b/src/test/rustdoc-json/fns/generic_args.rs index 98ba8e99d82..eec295efec0 100644 --- a/src/test/rustdoc-json/fns/generic_args.rs +++ b/src/test/rustdoc-json/fns/generic_args.rs @@ -3,65 +3,65 @@ #![feature(no_core)] #![no_core] -// @set foo = generic_args.json "$.index[*][?(@.name=='Foo')].id" +// @set foo = "$.index[*][?(@.name=='Foo')].id" pub trait Foo {} -// @set generic_foo = generic_args.json "$.index[*][?(@.name=='GenericFoo')].id" +// @set generic_foo = "$.index[*][?(@.name=='GenericFoo')].id" pub trait GenericFoo<'a> {} -// @is - "$.index[*][?(@.name=='generics')].inner.generics.where_predicates" "[]" -// @count - "$.index[*][?(@.name=='generics')].inner.generics.params[*]" 1 -// @is - "$.index[*][?(@.name=='generics')].inner.generics.params[0].name" '"F"' -// @is - "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.default" 'null' -// @count - "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.bounds[*]" 1 -// @is - "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" '$foo' -// @count - "$.index[*][?(@.name=='generics')].inner.decl.inputs[*]" 1 -// @is - "$.index[*][?(@.name=='generics')].inner.decl.inputs[0][0]" '"f"' -// @is - "$.index[*][?(@.name=='generics')].inner.decl.inputs[0][1].kind" '"generic"' -// @is - "$.index[*][?(@.name=='generics')].inner.decl.inputs[0][1].inner" '"F"' +// @is "$.index[*][?(@.name=='generics')].inner.generics.where_predicates" "[]" +// @count "$.index[*][?(@.name=='generics')].inner.generics.params[*]" 1 +// @is "$.index[*][?(@.name=='generics')].inner.generics.params[0].name" '"F"' +// @is "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.default" 'null' +// @count "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.bounds[*]" 1 +// @is "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" '$foo' +// @count "$.index[*][?(@.name=='generics')].inner.decl.inputs[*]" 1 +// @is "$.index[*][?(@.name=='generics')].inner.decl.inputs[0][0]" '"f"' +// @is "$.index[*][?(@.name=='generics')].inner.decl.inputs[0][1].kind" '"generic"' +// @is "$.index[*][?(@.name=='generics')].inner.decl.inputs[0][1].inner" '"F"' pub fn generics(f: F) {} -// @is - "$.index[*][?(@.name=='impl_trait')].inner.generics.where_predicates" "[]" -// @count - "$.index[*][?(@.name=='impl_trait')].inner.generics.params[*]" 1 -// @is - "$.index[*][?(@.name=='impl_trait')].inner.generics.params[0].name" '"impl Foo"' -// @is - "$.index[*][?(@.name=='impl_trait')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $foo -// @count - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[*]" 1 -// @is - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][0]" '"f"' -// @is - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].kind" '"impl_trait"' -// @count - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].inner[*]" 1 -// @is - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.id" $foo +// @is "$.index[*][?(@.name=='impl_trait')].inner.generics.where_predicates" "[]" +// @count "$.index[*][?(@.name=='impl_trait')].inner.generics.params[*]" 1 +// @is "$.index[*][?(@.name=='impl_trait')].inner.generics.params[0].name" '"impl Foo"' +// @is "$.index[*][?(@.name=='impl_trait')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $foo +// @count "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[*]" 1 +// @is "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][0]" '"f"' +// @is "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].kind" '"impl_trait"' +// @count "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].inner[*]" 1 +// @is "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.id" $foo pub fn impl_trait(f: impl Foo) {} -// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.params[*]" 3 -// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.params[0].name" '"F"' -// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.params[0].kind" '{"type": {"bounds": [], "default": null, "synthetic": false}}' -// @count - "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[*]" 3 -// @is - "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[0][0]" '"f"' -// @is - "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[0][1].kind" '"generic"' -// @is - "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[0][1].inner" '"F"' -// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[*]" 3 +// @count "$.index[*][?(@.name=='where_clase')].inner.generics.params[*]" 3 +// @is "$.index[*][?(@.name=='where_clase')].inner.generics.params[0].name" '"F"' +// @is "$.index[*][?(@.name=='where_clase')].inner.generics.params[0].kind" '{"type": {"bounds": [], "default": null, "synthetic": false}}' +// @count "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[*]" 3 +// @is "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[0][0]" '"f"' +// @is "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[0][1].kind" '"generic"' +// @is "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[0][1].inner" '"F"' +// @count "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[*]" 3 -// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.type" '{"inner": "F", "kind": "generic"}' -// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.bounds[*]" 1 -// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.bounds[0].trait_bound.trait.id" $foo +// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.type" '{"inner": "F", "kind": "generic"}' +// @count "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.bounds[*]" 1 +// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.bounds[0].trait_bound.trait.id" $foo -// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.type" '{"inner": "G", "kind": "generic"}' -// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[*]" 1 -// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.trait.id" $generic_foo -// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[*]" 1 -// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].name" \"\'a\" -// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }' -// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.generic_params" "[]" +// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.type" '{"inner": "G", "kind": "generic"}' +// @count "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[*]" 1 +// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.trait.id" $generic_foo +// @count "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[*]" 1 +// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].name" \"\'a\" +// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }' +// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.generic_params" "[]" -// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.kind" '"borrowed_ref"' -// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.inner.lifetime" \"\'b\" -// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.inner.type" '{"inner": "H", "kind": "generic"}' -// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[*]" 1 -// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.trait.id" $foo -// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.generic_params" "[]" -// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[*]" 1 -// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[0].name" \"\'b\" -// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }' +// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.kind" '"borrowed_ref"' +// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.inner.lifetime" \"\'b\" +// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.inner.type" '{"inner": "H", "kind": "generic"}' +// @count "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[*]" 1 +// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.trait.id" $foo +// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.generic_params" "[]" +// @count "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[*]" 1 +// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[0].name" \"\'b\" +// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }' pub fn where_clase(f: F, g: G, h: H) where F: Foo, diff --git a/src/test/rustdoc-json/fns/generic_returns.rs b/src/test/rustdoc-json/fns/generic_returns.rs index 46f250a99b9..a9bc2d5d727 100644 --- a/src/test/rustdoc-json/fns/generic_returns.rs +++ b/src/test/rustdoc-json/fns/generic_returns.rs @@ -3,15 +3,15 @@ #![feature(no_core)] #![no_core] -// @count generic_returns.json "$.index[*][?(@.name=='generic_returns')].inner.items[*]" 2 +// @count "$.index[*][?(@.name=='generic_returns')].inner.items[*]" 2 -// @set foo = - "$.index[*][?(@.name=='Foo')].id" +// @set foo = "$.index[*][?(@.name=='Foo')].id" pub trait Foo {} -// @is - "$.index[*][?(@.name=='get_foo')].inner.decl.inputs" [] -// @is - "$.index[*][?(@.name=='get_foo')].inner.decl.output.kind" '"impl_trait"' -// @count - "$.index[*][?(@.name=='get_foo')].inner.decl.output.inner[*]" 1 -// @is - "$.index[*][?(@.name=='get_foo')].inner.decl.output.inner[0].trait_bound.trait.id" $foo +// @is "$.index[*][?(@.name=='get_foo')].inner.decl.inputs" [] +// @is "$.index[*][?(@.name=='get_foo')].inner.decl.output.kind" '"impl_trait"' +// @count "$.index[*][?(@.name=='get_foo')].inner.decl.output.inner[*]" 1 +// @is "$.index[*][?(@.name=='get_foo')].inner.decl.output.inner[0].trait_bound.trait.id" $foo pub fn get_foo() -> impl Foo { Fooer {} } diff --git a/src/test/rustdoc-json/fns/generics.rs b/src/test/rustdoc-json/fns/generics.rs index e55e1e9400d..e47c8c25513 100644 --- a/src/test/rustdoc-json/fns/generics.rs +++ b/src/test/rustdoc-json/fns/generics.rs @@ -3,24 +3,24 @@ #![feature(no_core)] #![no_core] -// @set wham_id = generics.json "$.index[*][?(@.name=='Wham')].id" +// @set wham_id = "$.index[*][?(@.name=='Wham')].id" pub trait Wham {} -// @is - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.where_predicates" [] -// @count - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[*]" 1 -// @is - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].name" '"T"' -// @has - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" false -// @has - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id -// @is - "$.index[*][?(@.name=='one_generic_param_fn')].inner.decl.inputs" '[["w", {"inner": "T", "kind": "generic"}]]' +// @is "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.where_predicates" [] +// @count "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[*]" 1 +// @is "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].name" '"T"' +// @has "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" false +// @has "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id +// @is "$.index[*][?(@.name=='one_generic_param_fn')].inner.decl.inputs" '[["w", {"inner": "T", "kind": "generic"}]]' pub fn one_generic_param_fn(w: T) {} -// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.where_predicates" [] -// @count - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[*]" 1 -// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].name" '"impl Wham"' -// @has - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" true -// @has - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id -// @count - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[*]" 1 -// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][0]" '"w"' -// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].kind" '"impl_trait"' -// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.id" $wham_id +// @is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.where_predicates" [] +// @count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[*]" 1 +// @is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].name" '"impl Wham"' +// @has "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" true +// @has "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id +// @count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[*]" 1 +// @is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][0]" '"w"' +// @is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].kind" '"impl_trait"' +// @is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.id" $wham_id pub fn one_synthetic_generic_param_fn(w: impl Wham) {} diff --git a/src/test/rustdoc-json/fns/qualifiers.rs b/src/test/rustdoc-json/fns/qualifiers.rs index 5cb3b43e66a..7ff54290042 100644 --- a/src/test/rustdoc-json/fns/qualifiers.rs +++ b/src/test/rustdoc-json/fns/qualifiers.rs @@ -1,33 +1,33 @@ // edition:2018 -// @is qualifiers.json "$.index[*][?(@.name=='nothing_fn')].inner.header.async" false -// @is - "$.index[*][?(@.name=='nothing_fn')].inner.header.const" false -// @is - "$.index[*][?(@.name=='nothing_fn')].inner.header.unsafe" false +// @is "$.index[*][?(@.name=='nothing_fn')].inner.header.async" false +// @is "$.index[*][?(@.name=='nothing_fn')].inner.header.const" false +// @is "$.index[*][?(@.name=='nothing_fn')].inner.header.unsafe" false pub fn nothing_fn() {} -// @is - "$.index[*][?(@.name=='unsafe_fn')].inner.header.async" false -// @is - "$.index[*][?(@.name=='unsafe_fn')].inner.header.const" false -// @is - "$.index[*][?(@.name=='unsafe_fn')].inner.header.unsafe" true +// @is "$.index[*][?(@.name=='unsafe_fn')].inner.header.async" false +// @is "$.index[*][?(@.name=='unsafe_fn')].inner.header.const" false +// @is "$.index[*][?(@.name=='unsafe_fn')].inner.header.unsafe" true pub unsafe fn unsafe_fn() {} -// @is - "$.index[*][?(@.name=='const_fn')].inner.header.async" false -// @is - "$.index[*][?(@.name=='const_fn')].inner.header.const" true -// @is - "$.index[*][?(@.name=='const_fn')].inner.header.unsafe" false +// @is "$.index[*][?(@.name=='const_fn')].inner.header.async" false +// @is "$.index[*][?(@.name=='const_fn')].inner.header.const" true +// @is "$.index[*][?(@.name=='const_fn')].inner.header.unsafe" false pub const fn const_fn() {} -// @is - "$.index[*][?(@.name=='async_fn')].inner.header.async" true -// @is - "$.index[*][?(@.name=='async_fn')].inner.header.const" false -// @is - "$.index[*][?(@.name=='async_fn')].inner.header.unsafe" false +// @is "$.index[*][?(@.name=='async_fn')].inner.header.async" true +// @is "$.index[*][?(@.name=='async_fn')].inner.header.const" false +// @is "$.index[*][?(@.name=='async_fn')].inner.header.unsafe" false pub async fn async_fn() {} -// @is - "$.index[*][?(@.name=='async_unsafe_fn')].inner.header.async" true -// @is - "$.index[*][?(@.name=='async_unsafe_fn')].inner.header.const" false -// @is - "$.index[*][?(@.name=='async_unsafe_fn')].inner.header.unsafe" true +// @is "$.index[*][?(@.name=='async_unsafe_fn')].inner.header.async" true +// @is "$.index[*][?(@.name=='async_unsafe_fn')].inner.header.const" false +// @is "$.index[*][?(@.name=='async_unsafe_fn')].inner.header.unsafe" true pub async unsafe fn async_unsafe_fn() {} -// @is - "$.index[*][?(@.name=='const_unsafe_fn')].inner.header.async" false -// @is - "$.index[*][?(@.name=='const_unsafe_fn')].inner.header.const" true -// @is - "$.index[*][?(@.name=='const_unsafe_fn')].inner.header.unsafe" true +// @is "$.index[*][?(@.name=='const_unsafe_fn')].inner.header.async" false +// @is "$.index[*][?(@.name=='const_unsafe_fn')].inner.header.const" true +// @is "$.index[*][?(@.name=='const_unsafe_fn')].inner.header.unsafe" true pub const unsafe fn const_unsafe_fn() {} // It's impossible for a function to be both const and async, so no test for that diff --git a/src/test/rustdoc-json/generic-associated-types/gats.rs b/src/test/rustdoc-json/generic-associated-types/gats.rs index 368ff8d8da0..cbaa0621dc2 100644 --- a/src/test/rustdoc-json/generic-associated-types/gats.rs +++ b/src/test/rustdoc-json/generic-associated-types/gats.rs @@ -8,37 +8,35 @@ pub trait Sized {} pub trait Display {} -// @has gats.json pub trait LendingIterator { - // @count - "$.index[*][?(@.name=='LendingItem')].inner.generics.params[*]" 1 - // @is - "$.index[*][?(@.name=='LendingItem')].inner.generics.params[*].name" \"\'a\" - // @count - "$.index[*][?(@.name=='LendingItem')].inner.generics.where_predicates[*]" 1 - // @is - "$.index[*][?(@.name=='LendingItem')].inner.generics.where_predicates[*].bound_predicate.type.inner" \"Self\" - // @is - "$.index[*][?(@.name=='LendingItem')].inner.generics.where_predicates[*].bound_predicate.bounds[*].outlives" \"\'a\" - // @count - "$.index[*][?(@.name=='LendingItem')].inner.bounds[*]" 1 + // @count "$.index[*][?(@.name=='LendingItem')].inner.generics.params[*]" 1 + // @is "$.index[*][?(@.name=='LendingItem')].inner.generics.params[*].name" \"\'a\" + // @count "$.index[*][?(@.name=='LendingItem')].inner.generics.where_predicates[*]" 1 + // @is "$.index[*][?(@.name=='LendingItem')].inner.generics.where_predicates[*].bound_predicate.type.inner" \"Self\" + // @is "$.index[*][?(@.name=='LendingItem')].inner.generics.where_predicates[*].bound_predicate.bounds[*].outlives" \"\'a\" + // @count "$.index[*][?(@.name=='LendingItem')].inner.bounds[*]" 1 type LendingItem<'a>: Display where Self: 'a; - // @is - "$.index[*][?(@.name=='lending_next')].inner.decl.output.kind" \"qualified_path\" - // @count - "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.args.angle_bracketed.args[*]" 1 - // @count - "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.args.angle_bracketed.bindings[*]" 0 - // @is - "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.self_type.inner" \"Self\" - // @is - "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.name" \"LendingItem\" + // @is "$.index[*][?(@.name=='lending_next')].inner.decl.output.kind" \"qualified_path\" + // @count "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.args.angle_bracketed.args[*]" 1 + // @count "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.args.angle_bracketed.bindings[*]" 0 + // @is "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.self_type.inner" \"Self\" + // @is "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.name" \"LendingItem\" fn lending_next<'a>(&'a self) -> Self::LendingItem<'a>; } -// @has gats.json pub trait Iterator { - // @count - "$.index[*][?(@.name=='Item')].inner.generics.params[*]" 0 - // @count - "$.index[*][?(@.name=='Item')].inner.generics.where_predicates[*]" 0 - // @count - "$.index[*][?(@.name=='Item')].inner.bounds[*]" 1 + // @count "$.index[*][?(@.name=='Item')].inner.generics.params[*]" 0 + // @count "$.index[*][?(@.name=='Item')].inner.generics.where_predicates[*]" 0 + // @count "$.index[*][?(@.name=='Item')].inner.bounds[*]" 1 type Item: Display; - // @is - "$.index[*][?(@.name=='next')].inner.decl.output.kind" \"qualified_path\" - // @count - "$.index[*][?(@.name=='next')].inner.decl.output.inner.args.angle_bracketed.args[*]" 0 - // @count - "$.index[*][?(@.name=='next')].inner.decl.output.inner.args.angle_bracketed.bindings[*]" 0 - // @is - "$.index[*][?(@.name=='next')].inner.decl.output.inner.self_type.inner" \"Self\" - // @is - "$.index[*][?(@.name=='next')].inner.decl.output.inner.name" \"Item\" + // @is "$.index[*][?(@.name=='next')].inner.decl.output.kind" \"qualified_path\" + // @count "$.index[*][?(@.name=='next')].inner.decl.output.inner.args.angle_bracketed.args[*]" 0 + // @count "$.index[*][?(@.name=='next')].inner.decl.output.inner.args.angle_bracketed.bindings[*]" 0 + // @is "$.index[*][?(@.name=='next')].inner.decl.output.inner.self_type.inner" \"Self\" + // @is "$.index[*][?(@.name=='next')].inner.decl.output.inner.name" \"Item\" fn next<'a>(&'a self) -> Self::Item; } diff --git a/src/test/rustdoc-json/generic_impl.rs b/src/test/rustdoc-json/generic_impl.rs index ac68ba578b6..31f41d0f335 100644 --- a/src/test/rustdoc-json/generic_impl.rs +++ b/src/test/rustdoc-json/generic_impl.rs @@ -1,9 +1,8 @@ // Regression test for . -// @has generic_impl.json -// @has - "$.index[*][?(@.name=='f')]" -// @has - "$.index[*][?(@.name=='AssocTy')]" -// @has - "$.index[*][?(@.name=='AssocConst')]" +// @has "$.index[*][?(@.name=='f')]" +// @has "$.index[*][?(@.name=='AssocTy')]" +// @has "$.index[*][?(@.name=='AssocConst')]" pub mod m { pub struct S; diff --git a/src/test/rustdoc-json/glob_import.rs b/src/test/rustdoc-json/glob_import.rs index d7ac952d1bb..00051b12199 100644 --- a/src/test/rustdoc-json/glob_import.rs +++ b/src/test/rustdoc-json/glob_import.rs @@ -4,9 +4,8 @@ #![no_std] #![no_core] -// @has glob_import.json -// @has - "$.index[*][?(@.name=='glob')]" -// @has - "$.index[*][?(@.kind=='import')].inner.name" \"*\" +// @has "$.index[*][?(@.name=='glob')]" +// @has "$.index[*][?(@.kind=='import')].inner.name" \"*\" mod m1 { diff --git a/src/test/rustdoc-json/impls/auto.rs b/src/test/rustdoc-json/impls/auto.rs index fb32d7c31bc..50d85241427 100644 --- a/src/test/rustdoc-json/impls/auto.rs +++ b/src/test/rustdoc-json/impls/auto.rs @@ -12,7 +12,7 @@ impl Foo { } // Testing spans, so all tests below code -// @is auto.json "$.index[*][?(@.kind=='impl' && @.inner.synthetic==true)].span" null -// @is - "$.index[*][?(@.docs=='has span')].span.begin" "[10, 0]" -// @is - "$.index[*][?(@.docs=='has span')].span.end" "[12, 1]" +// @is "$.index[*][?(@.kind=='impl' && @.inner.synthetic==true)].span" null +// @is "$.index[*][?(@.docs=='has span')].span.begin" "[10, 0]" +// @is "$.index[*][?(@.docs=='has span')].span.end" "[12, 1]" pub struct Foo; diff --git a/src/test/rustdoc-json/impls/blanket_with_local.rs b/src/test/rustdoc-json/impls/blanket_with_local.rs index a3d55b35f00..2fb4a84b9a6 100644 --- a/src/test/rustdoc-json/impls/blanket_with_local.rs +++ b/src/test/rustdoc-json/impls/blanket_with_local.rs @@ -1,11 +1,11 @@ // Test for the ICE in rust/83718 // A blanket impl plus a local type together shouldn't result in mismatched ID issues -// @has blanket_with_local.json "$.index[*][?(@.name=='Load')]" +// @has "$.index[*][?(@.name=='Load')]" pub trait Load { - // @has - "$.index[*][?(@.name=='load')]" + // @has "$.index[*][?(@.name=='load')]" fn load() {} - // @has - "$.index[*][?(@.name=='write')]" + // @has "$.index[*][?(@.name=='write')]" fn write(self) {} } @@ -14,5 +14,5 @@ impl

Load for P { fn write(self) {} } -// @has - "$.index[*][?(@.name=='Wrapper')]" +// @has "$.index[*][?(@.name=='Wrapper')]" pub struct Wrapper {} diff --git a/src/test/rustdoc-json/impls/import_from_private.rs b/src/test/rustdoc-json/impls/import_from_private.rs index ef4d8aa39f8..a34046ac12f 100644 --- a/src/test/rustdoc-json/impls/import_from_private.rs +++ b/src/test/rustdoc-json/impls/import_from_private.rs @@ -4,21 +4,21 @@ #![no_core] mod bar { - // @set baz = import_from_private.json "$.index[*][?(@.kind=='struct')].id" + // @set baz = "$.index[*][?(@.kind=='struct')].id" pub struct Baz; - // @set impl = - "$.index[*][?(@.kind=='impl')].id" + // @set impl = "$.index[*][?(@.kind=='impl')].id" impl Baz { - // @set doit = - "$.index[*][?(@.kind=='method')].id" + // @set doit = "$.index[*][?(@.kind=='method')].id" pub fn doit() {} } } -// @set import = - "$.index[*][?(@.kind=='import')].id" +// @set import = "$.index[*][?(@.kind=='import')].id" pub use bar::Baz; // FIXME(adotinthevoid): Use hasexact once #99474 lands -// @has - "$.index[*][?(@.kind=='module')].inner.items[*]" $import -// @is - "$.index[*][?(@.kind=='import')].inner.id" $baz -// @has - "$.index[*][?(@.kind=='struct')].inner.impls[*]" $impl -// @has - "$.index[*][?(@.kind=='impl')].inner.items[*]" $doit +// @has "$.index[*][?(@.kind=='module')].inner.items[*]" $import +// @is "$.index[*][?(@.kind=='import')].inner.id" $baz +// @has "$.index[*][?(@.kind=='struct')].inner.impls[*]" $impl +// @has "$.index[*][?(@.kind=='impl')].inner.items[*]" $doit diff --git a/src/test/rustdoc-json/keyword.rs b/src/test/rustdoc-json/keyword.rs index 78a843aca7b..3446b212c56 100644 --- a/src/test/rustdoc-json/keyword.rs +++ b/src/test/rustdoc-json/keyword.rs @@ -6,16 +6,15 @@ #![feature(rustdoc_internals)] #![no_std] -// @has keyword.json -// @!has - "$.index[*][?(@.name=='match')]" -// @has - "$.index[*][?(@.name=='foo')]" +// @!has "$.index[*][?(@.name=='match')]" +// @has "$.index[*][?(@.name=='foo')]" #[doc(keyword = "match")] /// this is a test! pub mod foo {} -// @!has - "$.index[*][?(@.name=='hello')]" -// @!has - "$.index[*][?(@.name=='bar')]" +// @!has "$.index[*][?(@.name=='hello')]" +// @!has "$.index[*][?(@.name=='bar')]" #[doc(keyword = "hello")] /// hello mod bar {} diff --git a/src/test/rustdoc-json/lifetime/longest.rs b/src/test/rustdoc-json/lifetime/longest.rs index 95b99599e73..326dab8e57a 100644 --- a/src/test/rustdoc-json/lifetime/longest.rs +++ b/src/test/rustdoc-json/lifetime/longest.rs @@ -3,30 +3,30 @@ #![feature(no_core)] #![no_core] -// @is longest.json "$.index[*][?(@.name=='longest')].inner.generics.params[0].name" \"\'a\" -// @is - "$.index[*][?(@.name=='longest')].inner.generics.params[0].kind" '{"lifetime": {"outlives": []}}' -// @is - "$.index[*][?(@.name=='longest')].inner.generics.params[0].kind" '{"lifetime": {"outlives": []}}' -// @count - "$.index[*][?(@.name=='longest')].inner.generics.params[*]" 1 -// @is - "$.index[*][?(@.name=='longest')].inner.generics.where_predicates" [] +// @is "$.index[*][?(@.name=='longest')].inner.generics.params[0].name" \"\'a\" +// @is "$.index[*][?(@.name=='longest')].inner.generics.params[0].kind" '{"lifetime": {"outlives": []}}' +// @is "$.index[*][?(@.name=='longest')].inner.generics.params[0].kind" '{"lifetime": {"outlives": []}}' +// @count "$.index[*][?(@.name=='longest')].inner.generics.params[*]" 1 +// @is "$.index[*][?(@.name=='longest')].inner.generics.where_predicates" [] -// @count - "$.index[*][?(@.name=='longest')].inner.decl.inputs[*]" 2 -// @is - "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][0]" '"l"' -// @is - "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][0]" '"r"' +// @count "$.index[*][?(@.name=='longest')].inner.decl.inputs[*]" 2 +// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][0]" '"l"' +// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][0]" '"r"' -// @is - "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][1].kind" '"borrowed_ref"' -// @is - "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][1].inner.lifetime" \"\'a\" -// @is - "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][1].inner.mutable" false -// @is - "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][1].inner.type" '{"inner": "str", "kind": "primitive"}' +// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][1].kind" '"borrowed_ref"' +// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][1].inner.lifetime" \"\'a\" +// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][1].inner.mutable" false +// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][1].inner.type" '{"inner": "str", "kind": "primitive"}' -// @is - "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][1].kind" '"borrowed_ref"' -// @is - "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][1].inner.lifetime" \"\'a\" -// @is - "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][1].inner.mutable" false -// @is - "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][1].inner.type" '{"inner": "str", "kind": "primitive"}' +// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][1].kind" '"borrowed_ref"' +// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][1].inner.lifetime" \"\'a\" +// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][1].inner.mutable" false +// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][1].inner.type" '{"inner": "str", "kind": "primitive"}' -// @is - "$.index[*][?(@.name=='longest')].inner.decl.output.kind" '"borrowed_ref"' -// @is - "$.index[*][?(@.name=='longest')].inner.decl.output.inner.lifetime" \"\'a\" -// @is - "$.index[*][?(@.name=='longest')].inner.decl.output.inner.mutable" false -// @is - "$.index[*][?(@.name=='longest')].inner.decl.output.inner.type" '{"inner": "str", "kind": "primitive"}' +// @is "$.index[*][?(@.name=='longest')].inner.decl.output.kind" '"borrowed_ref"' +// @is "$.index[*][?(@.name=='longest')].inner.decl.output.inner.lifetime" \"\'a\" +// @is "$.index[*][?(@.name=='longest')].inner.decl.output.inner.mutable" false +// @is "$.index[*][?(@.name=='longest')].inner.decl.output.inner.type" '{"inner": "str", "kind": "primitive"}' pub fn longest<'a>(l: &'a str, r: &'a str) -> &'a str { if l.len() > r.len() { l } else { r } diff --git a/src/test/rustdoc-json/lifetime/outlives.rs b/src/test/rustdoc-json/lifetime/outlives.rs index 096dd7f7a69..e15a533efdc 100644 --- a/src/test/rustdoc-json/lifetime/outlives.rs +++ b/src/test/rustdoc-json/lifetime/outlives.rs @@ -3,21 +3,21 @@ #![feature(no_core)] #![no_core] -// @count outlives.json "$.index[*][?(@.name=='foo')].inner.generics.params[*]" 3 -// @is - "$.index[*][?(@.name=='foo')].inner.generics.where_predicates" [] -// @is - "$.index[*][?(@.name=='foo')].inner.generics.params[0].name" \"\'a\" -// @is - "$.index[*][?(@.name=='foo')].inner.generics.params[1].name" \"\'b\" -// @is - "$.index[*][?(@.name=='foo')].inner.generics.params[2].name" '"T"' -// @is - "$.index[*][?(@.name=='foo')].inner.generics.params[0].kind.lifetime.outlives" [] -// @is - "$.index[*][?(@.name=='foo')].inner.generics.params[1].kind.lifetime.outlives" [\"\'a\"] -// @is - "$.index[*][?(@.name=='foo')].inner.generics.params[2].kind.type.default" null -// @count - "$.index[*][?(@.name=='foo')].inner.generics.params[2].kind.type.bounds[*]" 1 -// @is - "$.index[*][?(@.name=='foo')].inner.generics.params[2].kind.type.bounds[0].outlives" \"\'b\" -// @is - "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].kind" '"borrowed_ref"' -// @is - "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.lifetime" \"\'a\" -// @is - "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.mutable" false -// @is - "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.type.kind" '"borrowed_ref"' -// @is - "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.type.inner.lifetime" \"\'b\" -// @is - "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.type.inner.mutable" false -// @is - "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.type.inner.type" '{"inner": "T", "kind": "generic"}' +// @count "$.index[*][?(@.name=='foo')].inner.generics.params[*]" 3 +// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates" [] +// @is "$.index[*][?(@.name=='foo')].inner.generics.params[0].name" \"\'a\" +// @is "$.index[*][?(@.name=='foo')].inner.generics.params[1].name" \"\'b\" +// @is "$.index[*][?(@.name=='foo')].inner.generics.params[2].name" '"T"' +// @is "$.index[*][?(@.name=='foo')].inner.generics.params[0].kind.lifetime.outlives" [] +// @is "$.index[*][?(@.name=='foo')].inner.generics.params[1].kind.lifetime.outlives" [\"\'a\"] +// @is "$.index[*][?(@.name=='foo')].inner.generics.params[2].kind.type.default" null +// @count "$.index[*][?(@.name=='foo')].inner.generics.params[2].kind.type.bounds[*]" 1 +// @is "$.index[*][?(@.name=='foo')].inner.generics.params[2].kind.type.bounds[0].outlives" \"\'b\" +// @is "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].kind" '"borrowed_ref"' +// @is "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.lifetime" \"\'a\" +// @is "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.mutable" false +// @is "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.type.kind" '"borrowed_ref"' +// @is "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.type.inner.lifetime" \"\'b\" +// @is "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.type.inner.mutable" false +// @is "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.type.inner.type" '{"inner": "T", "kind": "generic"}' pub fn foo<'a, 'b: 'a, T: 'b>(_: &'a &'b T) {} diff --git a/src/test/rustdoc-json/methods/abi.rs b/src/test/rustdoc-json/methods/abi.rs index 07b01d03bf6..4c97d97ceba 100644 --- a/src/test/rustdoc-json/methods/abi.rs +++ b/src/test/rustdoc-json/methods/abi.rs @@ -5,51 +5,51 @@ #![feature(no_core)] #![no_core] -// @has abi.json "$.index[*][?(@.name=='Foo')]" +// @has "$.index[*][?(@.name=='Foo')]" pub struct Foo; impl Foo { - // @is - "$.index[*][?(@.name=='abi_rust')].inner.header.abi" \"Rust\" + // @is "$.index[*][?(@.name=='abi_rust')].inner.header.abi" \"Rust\" pub fn abi_rust() {} - // @is - "$.index[*][?(@.name=='abi_c')].inner.header.abi" '{"C": {"unwind": false}}' + // @is "$.index[*][?(@.name=='abi_c')].inner.header.abi" '{"C": {"unwind": false}}' pub extern "C" fn abi_c() {} - // @is - "$.index[*][?(@.name=='abi_system')].inner.header.abi" '{"System": {"unwind": false}}' + // @is "$.index[*][?(@.name=='abi_system')].inner.header.abi" '{"System": {"unwind": false}}' pub extern "system" fn abi_system() {} - // @is - "$.index[*][?(@.name=='abi_c_unwind')].inner.header.abi" '{"C": {"unwind": true}}' + // @is "$.index[*][?(@.name=='abi_c_unwind')].inner.header.abi" '{"C": {"unwind": true}}' pub extern "C-unwind" fn abi_c_unwind() {} - // @is - "$.index[*][?(@.name=='abi_system_unwind')].inner.header.abi" '{"System": {"unwind": true}}' + // @is "$.index[*][?(@.name=='abi_system_unwind')].inner.header.abi" '{"System": {"unwind": true}}' pub extern "system-unwind" fn abi_system_unwind() {} - // @is - "$.index[*][?(@.name=='abi_vectorcall')].inner.header.abi.Other" '"\"vectorcall\""' + // @is "$.index[*][?(@.name=='abi_vectorcall')].inner.header.abi.Other" '"\"vectorcall\""' pub extern "vectorcall" fn abi_vectorcall() {} - // @is - "$.index[*][?(@.name=='abi_vectorcall_unwind')].inner.header.abi.Other" '"\"vectorcall-unwind\""' + // @is "$.index[*][?(@.name=='abi_vectorcall_unwind')].inner.header.abi.Other" '"\"vectorcall-unwind\""' pub extern "vectorcall-unwind" fn abi_vectorcall_unwind() {} } pub trait Bar { - // @is - "$.index[*][?(@.name=='trait_abi_rust')].inner.header.abi" \"Rust\" + // @is "$.index[*][?(@.name=='trait_abi_rust')].inner.header.abi" \"Rust\" fn trait_abi_rust() {} - // @is - "$.index[*][?(@.name=='trait_abi_c')].inner.header.abi" '{"C": {"unwind": false}}' + // @is "$.index[*][?(@.name=='trait_abi_c')].inner.header.abi" '{"C": {"unwind": false}}' extern "C" fn trait_abi_c() {} - // @is - "$.index[*][?(@.name=='trait_abi_system')].inner.header.abi" '{"System": {"unwind": false}}' + // @is "$.index[*][?(@.name=='trait_abi_system')].inner.header.abi" '{"System": {"unwind": false}}' extern "system" fn trait_abi_system() {} - // @is - "$.index[*][?(@.name=='trait_abi_c_unwind')].inner.header.abi" '{"C": {"unwind": true}}' + // @is "$.index[*][?(@.name=='trait_abi_c_unwind')].inner.header.abi" '{"C": {"unwind": true}}' extern "C-unwind" fn trait_abi_c_unwind() {} - // @is - "$.index[*][?(@.name=='trait_abi_system_unwind')].inner.header.abi" '{"System": {"unwind": true}}' + // @is "$.index[*][?(@.name=='trait_abi_system_unwind')].inner.header.abi" '{"System": {"unwind": true}}' extern "system-unwind" fn trait_abi_system_unwind() {} - // @is - "$.index[*][?(@.name=='trait_abi_vectorcall')].inner.header.abi.Other" '"\"vectorcall\""' + // @is "$.index[*][?(@.name=='trait_abi_vectorcall')].inner.header.abi.Other" '"\"vectorcall\""' extern "vectorcall" fn trait_abi_vectorcall() {} - // @is - "$.index[*][?(@.name=='trait_abi_vectorcall_unwind')].inner.header.abi.Other" '"\"vectorcall-unwind\""' + // @is "$.index[*][?(@.name=='trait_abi_vectorcall_unwind')].inner.header.abi.Other" '"\"vectorcall-unwind\""' extern "vectorcall-unwind" fn trait_abi_vectorcall_unwind() {} } diff --git a/src/test/rustdoc-json/methods/qualifiers.rs b/src/test/rustdoc-json/methods/qualifiers.rs index af36d36b660..b9a5e56012e 100644 --- a/src/test/rustdoc-json/methods/qualifiers.rs +++ b/src/test/rustdoc-json/methods/qualifiers.rs @@ -3,34 +3,34 @@ pub struct Foo; impl Foo { - // @is qualifiers.json "$.index[*][?(@.name=='const_meth')].inner.header.async" false - // @is - "$.index[*][?(@.name=='const_meth')].inner.header.const" true - // @is - "$.index[*][?(@.name=='const_meth')].inner.header.unsafe" false + // @is "$.index[*][?(@.name=='const_meth')].inner.header.async" false + // @is "$.index[*][?(@.name=='const_meth')].inner.header.const" true + // @is "$.index[*][?(@.name=='const_meth')].inner.header.unsafe" false pub const fn const_meth() {} - // @is - "$.index[*][?(@.name=='nothing_meth')].inner.header.async" false - // @is - "$.index[*][?(@.name=='nothing_meth')].inner.header.const" false - // @is - "$.index[*][?(@.name=='nothing_meth')].inner.header.unsafe" false + // @is "$.index[*][?(@.name=='nothing_meth')].inner.header.async" false + // @is "$.index[*][?(@.name=='nothing_meth')].inner.header.const" false + // @is "$.index[*][?(@.name=='nothing_meth')].inner.header.unsafe" false pub fn nothing_meth() {} - // @is - "$.index[*][?(@.name=='unsafe_meth')].inner.header.async" false - // @is - "$.index[*][?(@.name=='unsafe_meth')].inner.header.const" false - // @is - "$.index[*][?(@.name=='unsafe_meth')].inner.header.unsafe" true + // @is "$.index[*][?(@.name=='unsafe_meth')].inner.header.async" false + // @is "$.index[*][?(@.name=='unsafe_meth')].inner.header.const" false + // @is "$.index[*][?(@.name=='unsafe_meth')].inner.header.unsafe" true pub unsafe fn unsafe_meth() {} - // @is - "$.index[*][?(@.name=='async_meth')].inner.header.async" true - // @is - "$.index[*][?(@.name=='async_meth')].inner.header.const" false - // @is - "$.index[*][?(@.name=='async_meth')].inner.header.unsafe" false + // @is "$.index[*][?(@.name=='async_meth')].inner.header.async" true + // @is "$.index[*][?(@.name=='async_meth')].inner.header.const" false + // @is "$.index[*][?(@.name=='async_meth')].inner.header.unsafe" false pub async fn async_meth() {} - // @is - "$.index[*][?(@.name=='async_unsafe_meth')].inner.header.async" true - // @is - "$.index[*][?(@.name=='async_unsafe_meth')].inner.header.const" false - // @is - "$.index[*][?(@.name=='async_unsafe_meth')].inner.header.unsafe" true + // @is "$.index[*][?(@.name=='async_unsafe_meth')].inner.header.async" true + // @is "$.index[*][?(@.name=='async_unsafe_meth')].inner.header.const" false + // @is "$.index[*][?(@.name=='async_unsafe_meth')].inner.header.unsafe" true pub async unsafe fn async_unsafe_meth() {} - // @is - "$.index[*][?(@.name=='const_unsafe_meth')].inner.header.async" false - // @is - "$.index[*][?(@.name=='const_unsafe_meth')].inner.header.const" true - // @is - "$.index[*][?(@.name=='const_unsafe_meth')].inner.header.unsafe" true + // @is "$.index[*][?(@.name=='const_unsafe_meth')].inner.header.async" false + // @is "$.index[*][?(@.name=='const_unsafe_meth')].inner.header.const" true + // @is "$.index[*][?(@.name=='const_unsafe_meth')].inner.header.unsafe" true pub const unsafe fn const_unsafe_meth() {} // It's impossible for a method to be both const and async, so no test for that diff --git a/src/test/rustdoc-json/nested.rs b/src/test/rustdoc-json/nested.rs index 9ff1f60c0d5..73ec9392ce9 100644 --- a/src/test/rustdoc-json/nested.rs +++ b/src/test/rustdoc-json/nested.rs @@ -1,31 +1,31 @@ // edition:2018 // compile-flags: --crate-version 1.0.0 -// @is nested.json "$.crate_version" \"1.0.0\" -// @is - "$.index[*][?(@.name=='nested')].kind" \"module\" -// @is - "$.index[*][?(@.name=='nested')].inner.is_crate" true +// @is "$.crate_version" \"1.0.0\" +// @is "$.index[*][?(@.name=='nested')].kind" \"module\" +// @is "$.index[*][?(@.name=='nested')].inner.is_crate" true -// @set l1_id = - "$.index[*][?(@.name=='l1')].id" -// @ismany - "$.index[*][?(@.name=='nested')].inner.items[*]" $l1_id +// @set l1_id = "$.index[*][?(@.name=='l1')].id" +// @ismany "$.index[*][?(@.name=='nested')].inner.items[*]" $l1_id -// @is nested.json "$.index[*][?(@.name=='l1')].kind" \"module\" -// @is - "$.index[*][?(@.name=='l1')].inner.is_crate" false +// @is "$.index[*][?(@.name=='l1')].kind" \"module\" +// @is "$.index[*][?(@.name=='l1')].inner.is_crate" false pub mod l1 { - // @is nested.json "$.index[*][?(@.name=='l3')].kind" \"module\" - // @is - "$.index[*][?(@.name=='l3')].inner.is_crate" false - // @set l3_id = - "$.index[*][?(@.name=='l3')].id" + // @is "$.index[*][?(@.name=='l3')].kind" \"module\" + // @is "$.index[*][?(@.name=='l3')].inner.is_crate" false + // @set l3_id = "$.index[*][?(@.name=='l3')].id" pub mod l3 { - // @is nested.json "$.index[*][?(@.name=='L4')].kind" \"struct\" - // @is - "$.index[*][?(@.name=='L4')].inner.struct_type" \"unit\" - // @set l4_id = - "$.index[*][?(@.name=='L4')].id" - // @ismany - "$.index[*][?(@.name=='l3')].inner.items[*]" $l4_id + // @is "$.index[*][?(@.name=='L4')].kind" \"struct\" + // @is "$.index[*][?(@.name=='L4')].inner.struct_type" \"unit\" + // @set l4_id = "$.index[*][?(@.name=='L4')].id" + // @ismany "$.index[*][?(@.name=='l3')].inner.items[*]" $l4_id pub struct L4; } - // @is nested.json "$.index[*][?(@.inner.source=='l3::L4')].kind" \"import\" - // @is - "$.index[*][?(@.inner.source=='l3::L4')].inner.glob" false - // @is - "$.index[*][?(@.inner.source=='l3::L4')].inner.id" $l4_id - // @set l4_use_id = - "$.index[*][?(@.inner.source=='l3::L4')].id" + // @is "$.index[*][?(@.inner.source=='l3::L4')].kind" \"import\" + // @is "$.index[*][?(@.inner.source=='l3::L4')].inner.glob" false + // @is "$.index[*][?(@.inner.source=='l3::L4')].inner.id" $l4_id + // @set l4_use_id = "$.index[*][?(@.inner.source=='l3::L4')].id" pub use l3::L4; } -// @ismany - "$.index[*][?(@.name=='l1')].inner.items[*]" $l3_id $l4_use_id +// @ismany "$.index[*][?(@.name=='l1')].inner.items[*]" $l3_id $l4_use_id diff --git a/src/test/rustdoc-json/output_generics.rs b/src/test/rustdoc-json/output_generics.rs index d80656c7fc8..04b1a358fba 100644 --- a/src/test/rustdoc-json/output_generics.rs +++ b/src/test/rustdoc-json/output_generics.rs @@ -2,12 +2,11 @@ // This is a regression test for #98009. -// @has output_generics.json -// @has - "$.index[*][?(@.name=='this_compiles')]" -// @has - "$.index[*][?(@.name=='this_does_not')]" -// @has - "$.index[*][?(@.name=='Events')]" -// @has - "$.index[*][?(@.name=='Other')]" -// @has - "$.index[*][?(@.name=='Trait')]" +// @has "$.index[*][?(@.name=='this_compiles')]" +// @has "$.index[*][?(@.name=='this_does_not')]" +// @has "$.index[*][?(@.name=='Events')]" +// @has "$.index[*][?(@.name=='Other')]" +// @has "$.index[*][?(@.name=='Trait')]" struct Events(R); diff --git a/src/test/rustdoc-json/primitive.rs b/src/test/rustdoc-json/primitive.rs index 8d1141b5864..6454dd7f51f 100644 --- a/src/test/rustdoc-json/primitive.rs +++ b/src/test/rustdoc-json/primitive.rs @@ -5,16 +5,16 @@ #[doc(primitive = "usize")] mod usize {} -// @set local_crate_id = primitive.json "$.index[*][?(@.name=='primitive')].crate_id" +// @set local_crate_id = "$.index[*][?(@.name=='primitive')].crate_id" -// @has - "$.index[*][?(@.name=='ilog10')]" -// @!is - "$.index[*][?(@.name=='ilog10')].crate_id" $local_crate_id -// @has - "$.index[*][?(@.name=='checked_add')]" -// @!is - "$.index[*][?(@.name=='checked_add')]" $local_crate_id -// @!has - "$.index[*][?(@.name=='is_ascii_uppercase')]" +// @has "$.index[*][?(@.name=='ilog10')]" +// @!is "$.index[*][?(@.name=='ilog10')].crate_id" $local_crate_id +// @has "$.index[*][?(@.name=='checked_add')]" +// @!is "$.index[*][?(@.name=='checked_add')]" $local_crate_id +// @!has "$.index[*][?(@.name=='is_ascii_uppercase')]" -// @is - "$.index[*][?(@.kind=='import' && @.inner.name=='my_i32')].inner.id" null +// @is "$.index[*][?(@.kind=='import' && @.inner.name=='my_i32')].inner.id" null pub use i32 as my_i32; -// @is - "$.index[*][?(@.kind=='import' && @.inner.name=='u32')].inner.id" null +// @is "$.index[*][?(@.kind=='import' && @.inner.name=='u32')].inner.id" null pub use u32; diff --git a/src/test/rustdoc-json/primitive_overloading.rs b/src/test/rustdoc-json/primitive_overloading.rs index a10d5a83795..56b35cd14c0 100644 --- a/src/test/rustdoc-json/primitive_overloading.rs +++ b/src/test/rustdoc-json/primitive_overloading.rs @@ -7,9 +7,8 @@ #![no_core] -// @has primitive_overloading.json -// @has - "$.index[*][?(@.name=='usize')]" -// @has - "$.index[*][?(@.name=='prim')]" +// @has "$.index[*][?(@.name=='usize')]" +// @has "$.index[*][?(@.name=='prim')]" #[doc(primitive = "usize")] /// This is the built-in type `usize`. diff --git a/src/test/rustdoc-json/primitives.rs b/src/test/rustdoc-json/primitives.rs index fd04f04da06..491a7b1add4 100644 --- a/src/test/rustdoc-json/primitives.rs +++ b/src/test/rustdoc-json/primitives.rs @@ -1,22 +1,22 @@ #![feature(never_type)] -// @has primitives.json "$.index[*][?(@.name=='PrimNever')].visibility" \"public\" -// @has - "$.index[*][?(@.name=='PrimNever')].inner.type.kind" \"primitive\" -// @has - "$.index[*][?(@.name=='PrimNever')].inner.type.inner" \"never\" +// @has "$.index[*][?(@.name=='PrimNever')].visibility" \"public\" +// @has "$.index[*][?(@.name=='PrimNever')].inner.type.kind" \"primitive\" +// @has "$.index[*][?(@.name=='PrimNever')].inner.type.inner" \"never\" pub type PrimNever = !; -// @has - "$.index[*][?(@.name=='PrimStr')].inner.type.kind" \"primitive\" -// @has - "$.index[*][?(@.name=='PrimStr')].inner.type.inner" \"str\" +// @has "$.index[*][?(@.name=='PrimStr')].inner.type.kind" \"primitive\" +// @has "$.index[*][?(@.name=='PrimStr')].inner.type.inner" \"str\" pub type PrimStr = str; -// @has - "$.index[*][?(@.name=='PrimBool')].inner.type.kind" \"primitive\" -// @has - "$.index[*][?(@.name=='PrimBool')].inner.type.inner" \"bool\" +// @has "$.index[*][?(@.name=='PrimBool')].inner.type.kind" \"primitive\" +// @has "$.index[*][?(@.name=='PrimBool')].inner.type.inner" \"bool\" pub type PrimBool = bool; -// @has - "$.index[*][?(@.name=='PrimChar')].inner.type.kind" \"primitive\" -// @has - "$.index[*][?(@.name=='PrimChar')].inner.type.inner" \"char\" +// @has "$.index[*][?(@.name=='PrimChar')].inner.type.kind" \"primitive\" +// @has "$.index[*][?(@.name=='PrimChar')].inner.type.inner" \"char\" pub type PrimChar = char; -// @has - "$.index[*][?(@.name=='PrimU8')].inner.type.kind" \"primitive\" -// @has - "$.index[*][?(@.name=='PrimU8')].inner.type.inner" \"u8\" +// @has "$.index[*][?(@.name=='PrimU8')].inner.type.kind" \"primitive\" +// @has "$.index[*][?(@.name=='PrimU8')].inner.type.inner" \"u8\" pub type PrimU8 = u8; diff --git a/src/test/rustdoc-json/reexport/export_extern_crate_as_self.rs b/src/test/rustdoc-json/reexport/export_extern_crate_as_self.rs index fda38056a09..f076feb7185 100644 --- a/src/test/rustdoc-json/reexport/export_extern_crate_as_self.rs +++ b/src/test/rustdoc-json/reexport/export_extern_crate_as_self.rs @@ -7,5 +7,5 @@ // ignore-tidy-linelength -// @is export_extern_crate_as_self.json "$.index[*][?(@.kind=='module')].name" \"export_extern_crate_as_self\" +// @is "$.index[*][?(@.kind=='module')].name" \"export_extern_crate_as_self\" pub extern crate self as export_extern_crate_as_self; // Must be the same name as the crate already has diff --git a/src/test/rustdoc-json/reexport/glob_extern.rs b/src/test/rustdoc-json/reexport/glob_extern.rs index 4fe25904423..7a1e8c11ffa 100644 --- a/src/test/rustdoc-json/reexport/glob_extern.rs +++ b/src/test/rustdoc-json/reexport/glob_extern.rs @@ -3,21 +3,21 @@ #![no_core] #![feature(no_core)] -// @is glob_extern.json "$.index[*][?(@.name=='mod1')].kind" \"module\" -// @is - "$.index[*][?(@.name=='mod1')].inner.is_stripped" "true" +// @is "$.index[*][?(@.name=='mod1')].kind" \"module\" +// @is "$.index[*][?(@.name=='mod1')].inner.is_stripped" "true" mod mod1 { extern "C" { - // @set public_fn_id = - "$.index[*][?(@.name=='public_fn')].id" + // @set public_fn_id = "$.index[*][?(@.name=='public_fn')].id" pub fn public_fn(); - // @!has - "$.index[*][?(@.name=='private_fn')]" + // @!has "$.index[*][?(@.name=='private_fn')]" fn private_fn(); } - // @ismany - "$.index[*][?(@.name=='mod1')].inner.items[*]" $public_fn_id - // @set mod1_id = - "$.index[*][?(@.name=='mod1')].id" + // @ismany "$.index[*][?(@.name=='mod1')].inner.items[*]" $public_fn_id + // @set mod1_id = "$.index[*][?(@.name=='mod1')].id" } -// @is - "$.index[*][?(@.kind=='import')].inner.glob" true -// @is - "$.index[*][?(@.kind=='import')].inner.id" $mod1_id -// @set use_id = - "$.index[*][?(@.kind=='import')].id" -// @ismany - "$.index[*][?(@.name=='glob_extern')].inner.items[*]" $use_id +// @is "$.index[*][?(@.kind=='import')].inner.glob" true +// @is "$.index[*][?(@.kind=='import')].inner.id" $mod1_id +// @set use_id = "$.index[*][?(@.kind=='import')].id" +// @ismany "$.index[*][?(@.name=='glob_extern')].inner.items[*]" $use_id pub use mod1::*; diff --git a/src/test/rustdoc-json/reexport/glob_private.rs b/src/test/rustdoc-json/reexport/glob_private.rs index 04460a817f1..3a83a20818b 100644 --- a/src/test/rustdoc-json/reexport/glob_private.rs +++ b/src/test/rustdoc-json/reexport/glob_private.rs @@ -3,31 +3,31 @@ #![no_core] #![feature(no_core)] -// @is glob_private.json "$.index[*][?(@.name=='mod1')].kind" \"module\" -// @is glob_private.json "$.index[*][?(@.name=='mod1')].inner.is_stripped" "true" +// @is "$.index[*][?(@.name=='mod1')].kind" \"module\" +// @is "$.index[*][?(@.name=='mod1')].inner.is_stripped" "true" mod mod1 { - // @is - "$.index[*][?(@.name=='mod2')].kind" \"module\" - // @is - "$.index[*][?(@.name=='mod2')].inner.is_stripped" "true" + // @is "$.index[*][?(@.name=='mod2')].kind" \"module\" + // @is "$.index[*][?(@.name=='mod2')].inner.is_stripped" "true" mod mod2 { - // @set m2pub_id = - "$.index[*][?(@.name=='Mod2Public')].id" + // @set m2pub_id = "$.index[*][?(@.name=='Mod2Public')].id" pub struct Mod2Public; - // @!has - "$.index[*][?(@.name=='Mod2Private')]" + // @!has "$.index[*][?(@.name=='Mod2Private')]" struct Mod2Private; } - // @set mod2_use_id = - "$.index[*][?(@.kind=='import' && @.inner.name=='mod2')].id" + // @set mod2_use_id = "$.index[*][?(@.kind=='import' && @.inner.name=='mod2')].id" pub use self::mod2::*; - // @set m1pub_id = - "$.index[*][?(@.name=='Mod1Public')].id" + // @set m1pub_id = "$.index[*][?(@.name=='Mod1Public')].id" pub struct Mod1Public; - // @!has - "$.index[*][?(@.name=='Mod1Private')]" + // @!has "$.index[*][?(@.name=='Mod1Private')]" struct Mod1Private; } -// @set mod1_use_id = - "$.index[*][?(@.kind=='import' && @.inner.name=='mod1')].id" +// @set mod1_use_id = "$.index[*][?(@.kind=='import' && @.inner.name=='mod1')].id" pub use mod1::*; -// @ismany - "$.index[*][?(@.name=='mod2')].inner.items[*]" $m2pub_id -// @ismany - "$.index[*][?(@.name=='mod1')].inner.items[*]" $m1pub_id $mod2_use_id -// @ismany - "$.index[*][?(@.name=='glob_private')].inner.items[*]" $mod1_use_id +// @ismany "$.index[*][?(@.name=='mod2')].inner.items[*]" $m2pub_id +// @ismany "$.index[*][?(@.name=='mod1')].inner.items[*]" $m1pub_id $mod2_use_id +// @ismany "$.index[*][?(@.name=='glob_private')].inner.items[*]" $mod1_use_id diff --git a/src/test/rustdoc-json/reexport/in_root_and_mod.rs b/src/test/rustdoc-json/reexport/in_root_and_mod.rs index 7bf10a98686..68cb694f499 100644 --- a/src/test/rustdoc-json/reexport/in_root_and_mod.rs +++ b/src/test/rustdoc-json/reexport/in_root_and_mod.rs @@ -1,17 +1,17 @@ #![feature(no_core)] #![no_core] -// @is in_root_and_mod.json "$.index[*][?(@.name=='foo')].kind" \"module\" -// @is in_root_and_mod.json "$.index[*][?(@.name=='foo')].inner.is_stripped" "true" +// @is "$.index[*][?(@.name=='foo')].kind" \"module\" +// @is "$.index[*][?(@.name=='foo')].inner.is_stripped" "true" mod foo { - // @has - "$.index[*][?(@.name=='Foo')]" + // @has "$.index[*][?(@.name=='Foo')]" pub struct Foo; } -// @has - "$.index[*][?(@.kind=='import' && @.inner.source=='foo::Foo')]" +// @has "$.index[*][?(@.kind=='import' && @.inner.source=='foo::Foo')]" pub use foo::Foo; pub mod bar { - // @has - "$.index[*][?(@.kind=='import' && @.inner.source=='crate::foo::Foo')]" + // @has "$.index[*][?(@.kind=='import' && @.inner.source=='crate::foo::Foo')]" pub use crate::foo::Foo; } diff --git a/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs b/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs index 09302ee3acb..f6d932d927b 100644 --- a/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs +++ b/src/test/rustdoc-json/reexport/in_root_and_mod_pub.rs @@ -2,19 +2,19 @@ #![no_core] pub mod foo { - // @set bar_id = in_root_and_mod_pub.json "$.index[*][?(@.name=='Bar')].id" - // @ismany - "$.index[*][?(@.name=='foo')].inner.items[*]" $bar_id + // @set bar_id = "$.index[*][?(@.name=='Bar')].id" + // @ismany "$.index[*][?(@.name=='foo')].inner.items[*]" $bar_id pub struct Bar; } -// @set root_import_id = - "$.index[*][?(@.inner.source=='foo::Bar')].id" -// @is - "$.index[*][?(@.inner.source=='foo::Bar')].inner.id" $bar_id -// @has - "$.index[*][?(@.name=='in_root_and_mod_pub')].inner.items[*]" $root_import_id +// @set root_import_id = "$.index[*][?(@.inner.source=='foo::Bar')].id" +// @is "$.index[*][?(@.inner.source=='foo::Bar')].inner.id" $bar_id +// @has "$.index[*][?(@.name=='in_root_and_mod_pub')].inner.items[*]" $root_import_id pub use foo::Bar; pub mod baz { - // @set baz_import_id = - "$.index[*][?(@.inner.source=='crate::foo::Bar')].id" - // @is - "$.index[*][?(@.inner.source=='crate::foo::Bar')].inner.id" $bar_id - // @ismany - "$.index[*][?(@.name=='baz')].inner.items[*]" $baz_import_id + // @set baz_import_id = "$.index[*][?(@.inner.source=='crate::foo::Bar')].id" + // @is "$.index[*][?(@.inner.source=='crate::foo::Bar')].inner.id" $bar_id + // @ismany "$.index[*][?(@.name=='baz')].inner.items[*]" $baz_import_id pub use crate::foo::Bar; } diff --git a/src/test/rustdoc-json/reexport/macro.rs b/src/test/rustdoc-json/reexport/macro.rs index 0959736f309..b4882100f06 100644 --- a/src/test/rustdoc-json/reexport/macro.rs +++ b/src/test/rustdoc-json/reexport/macro.rs @@ -3,13 +3,13 @@ #![no_core] #![feature(no_core)] -// @set repro_id = macro.json "$.index[*][?(@.name=='repro')].id" +// @set repro_id = "$.index[*][?(@.name=='repro')].id" #[macro_export] macro_rules! repro { () => {}; } -// @set repro2_id = macro.json "$.index[*][?(@.inner.name=='repro2')].id" +// @set repro2_id = "$.index[*][?(@.inner.name=='repro2')].id" pub use crate::repro as repro2; -// @ismany macro.json "$.index[*][?(@.name=='macro')].inner.items[*]" $repro_id $repro2_id +// @ismany "$.index[*][?(@.name=='macro')].inner.items[*]" $repro_id $repro2_id diff --git a/src/test/rustdoc-json/reexport/private_twice_one_inline.rs b/src/test/rustdoc-json/reexport/private_twice_one_inline.rs index a76d352b28b..687a3b2ac8b 100644 --- a/src/test/rustdoc-json/reexport/private_twice_one_inline.rs +++ b/src/test/rustdoc-json/reexport/private_twice_one_inline.rs @@ -10,19 +10,19 @@ extern crate pub_struct as foo; #[doc(inline)] -// @set crate_use_id = private_twice_one_inline.json "$.index[*][?(@.docs=='Hack A')].id" -// @set foo_id = - "$.index[*][?(@.docs=='Hack A')].inner.id" +// @set crate_use_id = "$.index[*][?(@.docs=='Hack A')].id" +// @set foo_id = "$.index[*][?(@.docs=='Hack A')].inner.id" /// Hack A pub use foo::Foo; -// @set bar_id = - "$.index[*][?(@.name=='bar')].id" +// @set bar_id = "$.index[*][?(@.name=='bar')].id" pub mod bar { - // @is - "$.index[*][?(@.docs=='Hack B')].inner.id" $foo_id - // @set bar_use_id = - "$.index[*][?(@.docs=='Hack B')].id" - // @ismany - "$.index[*][?(@.name=='bar')].inner.items[*]" $bar_use_id + // @is "$.index[*][?(@.docs=='Hack B')].inner.id" $foo_id + // @set bar_use_id = "$.index[*][?(@.docs=='Hack B')].id" + // @ismany "$.index[*][?(@.name=='bar')].inner.items[*]" $bar_use_id /// Hack B pub use foo::Foo; } -// @ismany - "$.index[*][?(@.kind=='import')].id" $crate_use_id $bar_use_id -// @ismany - "$.index[*][?(@.name=='private_twice_one_inline')].inner.items[*]" $bar_id $crate_use_id +// @ismany "$.index[*][?(@.kind=='import')].id" $crate_use_id $bar_use_id +// @ismany "$.index[*][?(@.name=='private_twice_one_inline')].inner.items[*]" $bar_id $crate_use_id diff --git a/src/test/rustdoc-json/reexport/private_two_names.rs b/src/test/rustdoc-json/reexport/private_two_names.rs index cd8212cf344..ec78b06d09a 100644 --- a/src/test/rustdoc-json/reexport/private_two_names.rs +++ b/src/test/rustdoc-json/reexport/private_two_names.rs @@ -6,18 +6,18 @@ #![no_core] #![feature(no_core)] -// @is private_two_names.json "$.index[*][?(@.name=='style')].kind" \"module\" -// @is private_two_names.json "$.index[*][?(@.name=='style')].inner.is_stripped" "true" +// @is "$.index[*][?(@.name=='style')].kind" \"module\" +// @is "$.index[*][?(@.name=='style')].inner.is_stripped" "true" mod style { - // @set color_struct_id = - "$.index[*][?(@.kind=='struct' && @.name=='Color')].id" + // @set color_struct_id = "$.index[*][?(@.kind=='struct' && @.name=='Color')].id" pub struct Color; } -// @is - "$.index[*][?(@.kind=='import' && @.inner.name=='Color')].inner.id" $color_struct_id -// @set color_export_id = - "$.index[*][?(@.kind=='import' && @.inner.name=='Color')].id" +// @is "$.index[*][?(@.kind=='import' && @.inner.name=='Color')].inner.id" $color_struct_id +// @set color_export_id = "$.index[*][?(@.kind=='import' && @.inner.name=='Color')].id" pub use style::Color; -// @is - "$.index[*][?(@.kind=='import' && @.inner.name=='Colour')].inner.id" $color_struct_id -// @set colour_export_id = - "$.index[*][?(@.kind=='import' && @.inner.name=='Colour')].id" +// @is "$.index[*][?(@.kind=='import' && @.inner.name=='Colour')].inner.id" $color_struct_id +// @set colour_export_id = "$.index[*][?(@.kind=='import' && @.inner.name=='Colour')].id" pub use style::Color as Colour; -// @ismany - "$.index[*][?(@.name=='private_two_names')].inner.items[*]" $color_export_id $colour_export_id +// @ismany "$.index[*][?(@.name=='private_two_names')].inner.items[*]" $color_export_id $colour_export_id diff --git a/src/test/rustdoc-json/reexport/rename_private.rs b/src/test/rustdoc-json/reexport/rename_private.rs index 2476399bd56..1537f834481 100644 --- a/src/test/rustdoc-json/reexport/rename_private.rs +++ b/src/test/rustdoc-json/reexport/rename_private.rs @@ -3,12 +3,12 @@ #![no_core] #![feature(no_core)] -// @is rename_private.json "$.index[*][?(@.name=='inner')].kind" \"module\" -// @is rename_private.json "$.index[*][?(@.name=='inner')].inner.is_stripped" "true" +// @is "$.index[*][?(@.name=='inner')].kind" \"module\" +// @is "$.index[*][?(@.name=='inner')].inner.is_stripped" "true" mod inner { - // @has - "$.index[*][?(@.name=='Public')]" + // @has "$.index[*][?(@.name=='Public')]" pub struct Public; } -// @is - "$.index[*][?(@.kind=='import')].inner.name" \"NewName\" +// @is "$.index[*][?(@.kind=='import')].inner.name" \"NewName\" pub use inner::Public as NewName; diff --git a/src/test/rustdoc-json/reexport/rename_public.rs b/src/test/rustdoc-json/reexport/rename_public.rs index d41556974b4..e30907fe256 100644 --- a/src/test/rustdoc-json/reexport/rename_public.rs +++ b/src/test/rustdoc-json/reexport/rename_public.rs @@ -3,15 +3,15 @@ #![no_core] #![feature(no_core)] -// @set inner_id = rename_public.json "$.index[*][?(@.name=='inner')].id" +// @set inner_id = "$.index[*][?(@.name=='inner')].id" pub mod inner { - // @set public_id = - "$.index[*][?(@.name=='Public')].id" - // @ismany - "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id + // @set public_id = "$.index[*][?(@.name=='Public')].id" + // @ismany "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id pub struct Public; } -// @set import_id = - "$.index[*][?(@.inner.name=='NewName')].id" -// @!has - "$.index[*][?(@.inner.name=='Public')]" -// @is - "$.index[*][?(@.inner.name=='NewName')].inner.source" \"inner::Public\" +// @set import_id = "$.index[*][?(@.inner.name=='NewName')].id" +// @!has "$.index[*][?(@.inner.name=='Public')]" +// @is "$.index[*][?(@.inner.name=='NewName')].inner.source" \"inner::Public\" pub use inner::Public as NewName; -// @ismany - "$.index[*][?(@.name=='rename_public')].inner.items[*]" $inner_id $import_id +// @ismany "$.index[*][?(@.name=='rename_public')].inner.items[*]" $inner_id $import_id diff --git a/src/test/rustdoc-json/reexport/same_type_reexported_more_than_once.rs b/src/test/rustdoc-json/reexport/same_type_reexported_more_than_once.rs index 1d76c7e139b..880dbdc4416 100644 --- a/src/test/rustdoc-json/reexport/same_type_reexported_more_than_once.rs +++ b/src/test/rustdoc-json/reexport/same_type_reexported_more_than_once.rs @@ -6,18 +6,16 @@ #![no_std] #![no_core] -// @has same_type_reexported_more_than_once.json - mod inner { - // @set trait_id = - "$.index[*][?(@.name=='Trait')].id" + // @set trait_id = "$.index[*][?(@.name=='Trait')].id" pub trait Trait {} } -// @set export_id = - "$.index[*][?(@.inner.name=='Trait')].id" -// @is - "$.index[*][?(@.inner.name=='Trait')].inner.id" $trait_id +// @set export_id = "$.index[*][?(@.inner.name=='Trait')].id" +// @is "$.index[*][?(@.inner.name=='Trait')].inner.id" $trait_id pub use inner::Trait; -// @set reexport_id = - "$.index[*][?(@.inner.name=='Reexport')].id" -// @is - "$.index[*][?(@.inner.name=='Reexport')].inner.id" $trait_id +// @set reexport_id = "$.index[*][?(@.inner.name=='Reexport')].id" +// @is "$.index[*][?(@.inner.name=='Reexport')].inner.id" $trait_id pub use inner::Trait as Reexport; -// @ismany - "$.index[*][?(@.name=='same_type_reexported_more_than_once')].inner.items[*]" $reexport_id $export_id +// @ismany "$.index[*][?(@.name=='same_type_reexported_more_than_once')].inner.items[*]" $reexport_id $export_id diff --git a/src/test/rustdoc-json/reexport/simple_private.rs b/src/test/rustdoc-json/reexport/simple_private.rs index 55523bcd1de..82348b383c3 100644 --- a/src/test/rustdoc-json/reexport/simple_private.rs +++ b/src/test/rustdoc-json/reexport/simple_private.rs @@ -2,16 +2,16 @@ #![no_core] #![feature(no_core)] -// @is simple_private.json "$.index[*][?(@.name=='inner')].kind" \"module\" -// @is simple_private.json "$.index[*][?(@.name=='inner')].inner.is_stripped" "true" +// @is "$.index[*][?(@.name=='inner')].kind" \"module\" +// @is "$.index[*][?(@.name=='inner')].inner.is_stripped" "true" mod inner { - // @set pub_id = - "$.index[*][?(@.name=='Public')].id" + // @set pub_id = "$.index[*][?(@.name=='Public')].id" pub struct Public; } -// @is - "$.index[*][?(@.kind=='import')].inner.name" \"Public\" -// @set use_id = - "$.index[*][?(@.kind=='import')].id" +// @is "$.index[*][?(@.kind=='import')].inner.name" \"Public\" +// @set use_id = "$.index[*][?(@.kind=='import')].id" pub use inner::Public; -// @ismany - "$.index[*][?(@.name=='inner')].inner.items[*]" $pub_id -// @ismany - "$.index[*][?(@.name=='simple_private')].inner.items[*]" $use_id +// @ismany "$.index[*][?(@.name=='inner')].inner.items[*]" $pub_id +// @ismany "$.index[*][?(@.name=='simple_private')].inner.items[*]" $use_id diff --git a/src/test/rustdoc-json/reexport/simple_public.rs b/src/test/rustdoc-json/reexport/simple_public.rs index a3156a2b33a..e64a0dcb769 100644 --- a/src/test/rustdoc-json/reexport/simple_public.rs +++ b/src/test/rustdoc-json/reexport/simple_public.rs @@ -3,16 +3,16 @@ #![no_core] #![feature(no_core)] -// @set inner_id = simple_public.json "$.index[*][?(@.name=='inner')].id" +// @set inner_id = "$.index[*][?(@.name=='inner')].id" pub mod inner { - // @set public_id = - "$.index[*][?(@.name=='Public')].id" - // @ismany - "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id + // @set public_id = "$.index[*][?(@.name=='Public')].id" + // @ismany "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id pub struct Public; } -// @set import_id = - "$.index[*][?(@.inner.name=='Public')].id" -// @is - "$.index[*][?(@.inner.name=='Public')].inner.source" \"inner::Public\" +// @set import_id = "$.index[*][?(@.inner.name=='Public')].id" +// @is "$.index[*][?(@.inner.name=='Public')].inner.source" \"inner::Public\" pub use inner::Public; -// @ismany - "$.index[*][?(@.name=='simple_public')].inner.items[*]" $import_id $inner_id +// @ismany "$.index[*][?(@.name=='simple_public')].inner.items[*]" $import_id $inner_id diff --git a/src/test/rustdoc-json/return_private.rs b/src/test/rustdoc-json/return_private.rs index 6b324d0090a..a8d1fae30df 100644 --- a/src/test/rustdoc-json/return_private.rs +++ b/src/test/rustdoc-json/return_private.rs @@ -8,8 +8,8 @@ mod secret { pub struct Secret; } -// @is return_private.json "$.index[*][?(@.name=='get_secret')].kind" \"function\" -// @is return_private.json "$.index[*][?(@.name=='get_secret')].inner.decl.output.inner.name" \"secret::Secret\" +// @is "$.index[*][?(@.name=='get_secret')].kind" \"function\" +// @is "$.index[*][?(@.name=='get_secret')].inner.decl.output.inner.name" \"secret::Secret\" pub fn get_secret() -> secret::Secret { secret::Secret } diff --git a/src/test/rustdoc-json/stripped_modules.rs b/src/test/rustdoc-json/stripped_modules.rs index 91f9f02ad7b..33e95ce69d0 100644 --- a/src/test/rustdoc-json/stripped_modules.rs +++ b/src/test/rustdoc-json/stripped_modules.rs @@ -1,20 +1,20 @@ #![no_core] #![feature(no_core)] -// @!has stripped_modules.json "$.index[*][?(@.name=='no_pub_inner')]" +// @!has "$.index[*][?(@.name=='no_pub_inner')]" mod no_pub_inner { fn priv_inner() {} } -// @!has - "$.index[*][?(@.name=='pub_inner_unreachable')]" +// @!has "$.index[*][?(@.name=='pub_inner_unreachable')]" mod pub_inner_unreachable { - // @!has - "$.index[*][?(@.name=='pub_inner_1')]" + // @!has "$.index[*][?(@.name=='pub_inner_1')]" pub fn pub_inner_1() {} } -// @has - "$.index[*][?(@.name=='pub_inner_reachable')]" +// @has "$.index[*][?(@.name=='pub_inner_reachable')]" mod pub_inner_reachable { - // @has - "$.index[*][?(@.name=='pub_inner_2')]" + // @has "$.index[*][?(@.name=='pub_inner_2')]" pub fn pub_inner_2() {} } diff --git a/src/test/rustdoc-json/structs/plain_empty.rs b/src/test/rustdoc-json/structs/plain_empty.rs index a251caf4ba9..2ad9e86096c 100644 --- a/src/test/rustdoc-json/structs/plain_empty.rs +++ b/src/test/rustdoc-json/structs/plain_empty.rs @@ -1,6 +1,6 @@ -// @has plain_empty.json "$.index[*][?(@.name=='PlainEmpty')].visibility" \"public\" -// @has - "$.index[*][?(@.name=='PlainEmpty')].kind" \"struct\" -// @has - "$.index[*][?(@.name=='PlainEmpty')].inner.struct_type" \"plain\" -// @has - "$.index[*][?(@.name=='PlainEmpty')].inner.fields_stripped" false -// @has - "$.index[*][?(@.name=='PlainEmpty')].inner.fields" [] +// @has "$.index[*][?(@.name=='PlainEmpty')].visibility" \"public\" +// @has "$.index[*][?(@.name=='PlainEmpty')].kind" \"struct\" +// @has "$.index[*][?(@.name=='PlainEmpty')].inner.struct_type" \"plain\" +// @has "$.index[*][?(@.name=='PlainEmpty')].inner.fields_stripped" false +// @has "$.index[*][?(@.name=='PlainEmpty')].inner.fields" [] pub struct PlainEmpty {} diff --git a/src/test/rustdoc-json/structs/tuple.rs b/src/test/rustdoc-json/structs/tuple.rs index 4e510b39825..91fac359422 100644 --- a/src/test/rustdoc-json/structs/tuple.rs +++ b/src/test/rustdoc-json/structs/tuple.rs @@ -1,5 +1,5 @@ -// @has tuple.json "$.index[*][?(@.name=='Tuple')].visibility" \"public\" -// @has - "$.index[*][?(@.name=='Tuple')].kind" \"struct\" -// @has - "$.index[*][?(@.name=='Tuple')].inner.struct_type" \"tuple\" -// @has - "$.index[*][?(@.name=='Tuple')].inner.fields_stripped" true +// @has "$.index[*][?(@.name=='Tuple')].visibility" \"public\" +// @has "$.index[*][?(@.name=='Tuple')].kind" \"struct\" +// @has "$.index[*][?(@.name=='Tuple')].inner.struct_type" \"tuple\" +// @has "$.index[*][?(@.name=='Tuple')].inner.fields_stripped" true pub struct Tuple(u32, String); diff --git a/src/test/rustdoc-json/structs/unit.rs b/src/test/rustdoc-json/structs/unit.rs index 559d3068de6..85a515b5e78 100644 --- a/src/test/rustdoc-json/structs/unit.rs +++ b/src/test/rustdoc-json/structs/unit.rs @@ -1,5 +1,5 @@ -// @has unit.json "$.index[*][?(@.name=='Unit')].visibility" \"public\" -// @has - "$.index[*][?(@.name=='Unit')].kind" \"struct\" -// @has - "$.index[*][?(@.name=='Unit')].inner.struct_type" \"unit\" -// @has - "$.index[*][?(@.name=='Unit')].inner.fields" [] +// @has "$.index[*][?(@.name=='Unit')].visibility" \"public\" +// @has "$.index[*][?(@.name=='Unit')].kind" \"struct\" +// @has "$.index[*][?(@.name=='Unit')].inner.struct_type" \"unit\" +// @has "$.index[*][?(@.name=='Unit')].inner.fields" [] pub struct Unit; diff --git a/src/test/rustdoc-json/structs/with_generics.rs b/src/test/rustdoc-json/structs/with_generics.rs index 65cfe7effa5..b0ad1883f8a 100644 --- a/src/test/rustdoc-json/structs/with_generics.rs +++ b/src/test/rustdoc-json/structs/with_generics.rs @@ -1,13 +1,13 @@ use std::collections::HashMap; -// @has with_generics.json "$.index[*][?(@.name=='WithGenerics')].visibility" \"public\" -// @has - "$.index[*][?(@.name=='WithGenerics')].kind" \"struct\" -// @has - "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[0].name" \"T\" -// @has - "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[0].kind.type" -// @has - "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[1].name" \"U\" -// @has - "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[1].kind.type" -// @has - "$.index[*][?(@.name=='WithGenerics')].inner.struct_type" \"plain\" -// @has - "$.index[*][?(@.name=='WithGenerics')].inner.fields_stripped" true +// @has "$.index[*][?(@.name=='WithGenerics')].visibility" \"public\" +// @has "$.index[*][?(@.name=='WithGenerics')].kind" \"struct\" +// @has "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[0].name" \"T\" +// @has "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[0].kind.type" +// @has "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[1].name" \"U\" +// @has "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[1].kind.type" +// @has "$.index[*][?(@.name=='WithGenerics')].inner.struct_type" \"plain\" +// @has "$.index[*][?(@.name=='WithGenerics')].inner.fields_stripped" true pub struct WithGenerics { stuff: Vec, things: HashMap, diff --git a/src/test/rustdoc-json/structs/with_primitives.rs b/src/test/rustdoc-json/structs/with_primitives.rs index 9e64317ec20..b74050dde78 100644 --- a/src/test/rustdoc-json/structs/with_primitives.rs +++ b/src/test/rustdoc-json/structs/with_primitives.rs @@ -1,9 +1,9 @@ -// @has with_primitives.json "$.index[*][?(@.name=='WithPrimitives')].visibility" \"public\" -// @has - "$.index[*][?(@.name=='WithPrimitives')].kind" \"struct\" -// @has - "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].name" \"\'a\" -// @has - "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].kind.lifetime.outlives" [] -// @has - "$.index[*][?(@.name=='WithPrimitives')].inner.struct_type" \"plain\" -// @has - "$.index[*][?(@.name=='WithPrimitives')].inner.fields_stripped" true +// @has "$.index[*][?(@.name=='WithPrimitives')].visibility" \"public\" +// @has "$.index[*][?(@.name=='WithPrimitives')].kind" \"struct\" +// @has "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].name" \"\'a\" +// @has "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].kind.lifetime.outlives" [] +// @has "$.index[*][?(@.name=='WithPrimitives')].inner.struct_type" \"plain\" +// @has "$.index[*][?(@.name=='WithPrimitives')].inner.fields_stripped" true pub struct WithPrimitives<'a> { num: u32, s: &'a str, diff --git a/src/test/rustdoc-json/traits/has_body.rs b/src/test/rustdoc-json/traits/has_body.rs index 44dacb1ee75..4565aba6587 100644 --- a/src/test/rustdoc-json/traits/has_body.rs +++ b/src/test/rustdoc-json/traits/has_body.rs @@ -1,21 +1,21 @@ -// @has has_body.json "$.index[*][?(@.name=='Foo')]" +// @has "$.index[*][?(@.name=='Foo')]" pub trait Foo { - // @has - "$.index[*][?(@.name=='no_self')].inner.has_body" false + // @has "$.index[*][?(@.name=='no_self')].inner.has_body" false fn no_self(); - // @has - "$.index[*][?(@.name=='move_self')].inner.has_body" false + // @has "$.index[*][?(@.name=='move_self')].inner.has_body" false fn move_self(self); - // @has - "$.index[*][?(@.name=='ref_self')].inner.has_body" false + // @has "$.index[*][?(@.name=='ref_self')].inner.has_body" false fn ref_self(&self); - // @has - "$.index[*][?(@.name=='no_self_def')].inner.has_body" true + // @has "$.index[*][?(@.name=='no_self_def')].inner.has_body" true fn no_self_def() {} - // @has - "$.index[*][?(@.name=='move_self_def')].inner.has_body" true + // @has "$.index[*][?(@.name=='move_self_def')].inner.has_body" true fn move_self_def(self) {} - // @has - "$.index[*][?(@.name=='ref_self_def')].inner.has_body" true + // @has "$.index[*][?(@.name=='ref_self_def')].inner.has_body" true fn ref_self_def(&self) {} } pub trait Bar: Clone { - // @has - "$.index[*][?(@.name=='method')].inner.has_body" false + // @has "$.index[*][?(@.name=='method')].inner.has_body" false fn method(&self, param: usize); } diff --git a/src/test/rustdoc-json/traits/implementors.rs b/src/test/rustdoc-json/traits/implementors.rs index f7f03d98720..db3fe5df739 100644 --- a/src/test/rustdoc-json/traits/implementors.rs +++ b/src/test/rustdoc-json/traits/implementors.rs @@ -1,19 +1,19 @@ #![feature(no_core)] #![no_core] -// @set wham = implementors.json "$.index[*][?(@.name=='Wham')].id" -// @count - "$.index[*][?(@.name=='Wham')].inner.implementations[*]" 1 -// @set gmWham = - "$.index[*][?(@.name=='Wham')].inner.implementations[0]" +// @set wham = "$.index[*][?(@.name=='Wham')].id" +// @count "$.index[*][?(@.name=='Wham')].inner.implementations[*]" 1 +// @set gmWham = "$.index[*][?(@.name=='Wham')].inner.implementations[0]" pub trait Wham {} -// @count - "$.index[*][?(@.name=='GeorgeMichael')].inner.impls[*]" 1 -// @is - "$.index[*][?(@.name=='GeorgeMichael')].inner.impls[0]" $gmWham -// @set gm = - "$.index[*][?(@.name=='Wham')].id" +// @count "$.index[*][?(@.name=='GeorgeMichael')].inner.impls[*]" 1 +// @is "$.index[*][?(@.name=='GeorgeMichael')].inner.impls[0]" $gmWham +// @set gm = "$.index[*][?(@.name=='Wham')].id" // jsonpath_lib isnt expressive enough (for now) to get the "impl" item, so we // just check it isn't pointing to the type, but when you port to jsondocck-ng // check what the impl item is -// @!is - "$.index[*][?(@.name=='Wham')].inner.implementations[0]" $gm +// @!is "$.index[*][?(@.name=='Wham')].inner.implementations[0]" $gm pub struct GeorgeMichael {} impl Wham for GeorgeMichael {} diff --git a/src/test/rustdoc-json/traits/supertrait.rs b/src/test/rustdoc-json/traits/supertrait.rs index ce2f3912ba6..4048fdd74b4 100644 --- a/src/test/rustdoc-json/traits/supertrait.rs +++ b/src/test/rustdoc-json/traits/supertrait.rs @@ -4,23 +4,23 @@ #![feature(lang_items)] #![no_core] -// @set loud_id = supertrait.json "$.index[*][?(@.name=='Loud')].id" +// @set loud_id = "$.index[*][?(@.name=='Loud')].id" pub trait Loud {} -// @set very_loud_id = - "$.index[*][?(@.name=='VeryLoud')].id" -// @count - "$.index[*][?(@.name=='VeryLoud')].inner.bounds[*]" 1 -// @is - "$.index[*][?(@.name=='VeryLoud')].inner.bounds[0].trait_bound.trait.id" $loud_id +// @set very_loud_id = "$.index[*][?(@.name=='VeryLoud')].id" +// @count "$.index[*][?(@.name=='VeryLoud')].inner.bounds[*]" 1 +// @is "$.index[*][?(@.name=='VeryLoud')].inner.bounds[0].trait_bound.trait.id" $loud_id pub trait VeryLoud: Loud {} -// @set sounds_good_id = - "$.index[*][?(@.name=='SoundsGood')].id" +// @set sounds_good_id = "$.index[*][?(@.name=='SoundsGood')].id" pub trait SoundsGood {} -// @count - "$.index[*][?(@.name=='MetalBand')].inner.bounds[*]" 2 -// @is - "$.index[*][?(@.name=='MetalBand')].inner.bounds[0].trait_bound.trait.id" $very_loud_id -// @is - "$.index[*][?(@.name=='MetalBand')].inner.bounds[1].trait_bound.trait.id" $sounds_good_id +// @count "$.index[*][?(@.name=='MetalBand')].inner.bounds[*]" 2 +// @is "$.index[*][?(@.name=='MetalBand')].inner.bounds[0].trait_bound.trait.id" $very_loud_id +// @is "$.index[*][?(@.name=='MetalBand')].inner.bounds[1].trait_bound.trait.id" $sounds_good_id pub trait MetalBand: VeryLoud + SoundsGood {} -// @count - "$.index[*][?(@.name=='DnabLatem')].inner.bounds[*]" 2 -// @is - "$.index[*][?(@.name=='DnabLatem')].inner.bounds[1].trait_bound.trait.id" $very_loud_id -// @is - "$.index[*][?(@.name=='DnabLatem')].inner.bounds[0].trait_bound.trait.id" $sounds_good_id +// @count "$.index[*][?(@.name=='DnabLatem')].inner.bounds[*]" 2 +// @is "$.index[*][?(@.name=='DnabLatem')].inner.bounds[1].trait_bound.trait.id" $very_loud_id +// @is "$.index[*][?(@.name=='DnabLatem')].inner.bounds[0].trait_bound.trait.id" $sounds_good_id pub trait DnabLatem: SoundsGood + VeryLoud {} diff --git a/src/test/rustdoc-json/type/dyn.rs b/src/test/rustdoc-json/type/dyn.rs index 690dccc8287..03c6481f80e 100644 --- a/src/test/rustdoc-json/type/dyn.rs +++ b/src/test/rustdoc-json/type/dyn.rs @@ -1,48 +1,48 @@ // ignore-tidy-linelength use std::fmt::Debug; -// @count dyn.json "$.index[*][?(@.name=='dyn')].inner.items[*]" 3 -// @set sync_int_gen = - "$.index[*][?(@.name=='SyncIntGen')].id" -// @set ref_fn = - "$.index[*][?(@.name=='RefFn')].id" -// @set weird_order = - "$.index[*][?(@.name=='WeirdOrder')].id" -// @has - "$.index[*][?(@.name=='dyn')].inner.items[*]" $sync_int_gen -// @has - "$.index[*][?(@.name=='dyn')].inner.items[*]" $ref_fn -// @has - "$.index[*][?(@.name=='dyn')].inner.items[*]" $weird_order +// @count "$.index[*][?(@.name=='dyn')].inner.items[*]" 3 +// @set sync_int_gen = "$.index[*][?(@.name=='SyncIntGen')].id" +// @set ref_fn = "$.index[*][?(@.name=='RefFn')].id" +// @set weird_order = "$.index[*][?(@.name=='WeirdOrder')].id" +// @has "$.index[*][?(@.name=='dyn')].inner.items[*]" $sync_int_gen +// @has "$.index[*][?(@.name=='dyn')].inner.items[*]" $ref_fn +// @has "$.index[*][?(@.name=='dyn')].inner.items[*]" $weird_order -// @is - "$.index[*][?(@.name=='SyncIntGen')].kind" \"typedef\" -// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.generics" '{"params": [], "where_predicates": []}' -// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.kind" \"resolved_path\" -// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.name" \"Box\" -// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.bindings" [] -// @count - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args" 1 -// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"dyn_trait\" -// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.lifetime" \"\'static\" -// @count - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[*]" 3 -// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].generic_params" [] -// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].generic_params" [] -// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[2].generic_params" [] -// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.name" '"Fn"' -// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].trait.name" '"Send"' -// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[2].trait.name" '"Sync"' -// @is - "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.args" '{"parenthesized": {"inputs": [],"output": {"inner": "i32","kind": "primitive"}}}' +// @is "$.index[*][?(@.name=='SyncIntGen')].kind" \"typedef\" +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.generics" '{"params": [], "where_predicates": []}' +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type.kind" \"resolved_path\" +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.name" \"Box\" +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.bindings" [] +// @count "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args" 1 +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"dyn_trait\" +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.lifetime" \"\'static\" +// @count "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[*]" 3 +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].generic_params" [] +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].generic_params" [] +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[2].generic_params" [] +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.name" '"Fn"' +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].trait.name" '"Send"' +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[2].trait.name" '"Sync"' +// @is "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.args" '{"parenthesized": {"inputs": [],"output": {"inner": "i32","kind": "primitive"}}}' pub type SyncIntGen = Box i32 + Send + Sync + 'static>; -// @is - "$.index[*][?(@.name=='RefFn')].kind" \"typedef\" -// @is - "$.index[*][?(@.name=='RefFn')].inner.generics" '{"params": [{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"}],"where_predicates": []}' -// @is - "$.index[*][?(@.name=='RefFn')].inner.type.kind" '"borrowed_ref"' -// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.mutable" 'false' -// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.lifetime" "\"'a\"" -// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.kind" '"dyn_trait"' -// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.lifetime" null -// @count - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[*]" 1 -// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]' -// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.name" '"Fn"' -// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.inputs[0].kind" '"borrowed_ref"' -// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.inputs[0].inner.lifetime" "\"'b\"" -// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.output.kind" '"borrowed_ref"' -// @is - "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.output.inner.lifetime" "\"'b\"" +// @is "$.index[*][?(@.name=='RefFn')].kind" \"typedef\" +// @is "$.index[*][?(@.name=='RefFn')].inner.generics" '{"params": [{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"}],"where_predicates": []}' +// @is "$.index[*][?(@.name=='RefFn')].inner.type.kind" '"borrowed_ref"' +// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.mutable" 'false' +// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.lifetime" "\"'a\"" +// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.kind" '"dyn_trait"' +// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.lifetime" null +// @count "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[*]" 1 +// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]' +// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.name" '"Fn"' +// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.inputs[0].kind" '"borrowed_ref"' +// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.inputs[0].inner.lifetime" "\"'b\"" +// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.output.kind" '"borrowed_ref"' +// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.output.inner.lifetime" "\"'b\"" pub type RefFn<'a> = &'a dyn for<'b> Fn(&'b i32) -> &'b i32; -// @is - "$.index[*][?(@.name=='WeirdOrder')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.name" '"Send"' -// @is - "$.index[*][?(@.name=='WeirdOrder')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].trait.name" '"Debug"' +// @is "$.index[*][?(@.name=='WeirdOrder')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.name" '"Send"' +// @is "$.index[*][?(@.name=='WeirdOrder')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].trait.name" '"Debug"' pub type WeirdOrder = Box; diff --git a/src/test/rustdoc-json/type/fn_lifetime.rs b/src/test/rustdoc-json/type/fn_lifetime.rs index fd49a0890c0..d7216ec7675 100644 --- a/src/test/rustdoc-json/type/fn_lifetime.rs +++ b/src/test/rustdoc-json/type/fn_lifetime.rs @@ -1,27 +1,27 @@ // ignore-tidy-linelength -// @is fn_lifetime.json "$.index[*][?(@.name=='GenericFn')].kind" \"typedef\" +// @is "$.index[*][?(@.name=='GenericFn')].kind" \"typedef\" -// @ismany - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].name" \"\'a\" -// @has - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime" -// @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime.outlives[*]" 0 -// @count - "$.index[*][?(@.name=='GenericFn')].inner.generics.where_predicates[*]" 0 -// @is - "$.index[*][?(@.name=='GenericFn')].inner.type.kind" \"function_pointer\" -// @count - "$.index[*][?(@.name=='GenericFn')].inner.type.inner.generic_params[*]" 0 -// @count - "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.inputs[*]" 1 -// @is - "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.inputs[*][1].inner.lifetime" \"\'a\" -// @is - "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.output.inner.lifetime" \"\'a\" +// @ismany "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].name" \"\'a\" +// @has "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime" +// @count "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime.outlives[*]" 0 +// @count "$.index[*][?(@.name=='GenericFn')].inner.generics.where_predicates[*]" 0 +// @is "$.index[*][?(@.name=='GenericFn')].inner.type.kind" \"function_pointer\" +// @count "$.index[*][?(@.name=='GenericFn')].inner.type.inner.generic_params[*]" 0 +// @count "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.inputs[*]" 1 +// @is "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.inputs[*][1].inner.lifetime" \"\'a\" +// @is "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.output.inner.lifetime" \"\'a\" pub type GenericFn<'a> = fn(&'a i32) -> &'a i32; -// @is fn_lifetime.json "$.index[*][?(@.name=='ForAll')].kind" \"typedef\" -// @count - "$.index[*][?(@.name=='ForAll')].inner.generics.params[*]" 0 -// @count - "$.index[*][?(@.name=='ForAll')].inner.generics.where_predicates[*]" 0 -// @count - "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*]" 1 -// @is - "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].name" \"\'a\" -// @has - "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].kind.lifetime" -// @count - "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].kind.lifetime.outlives[*]" 0 -// @count - "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.inputs[*]" 1 -// @is - "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.inputs[*][1].inner.lifetime" \"\'a\" -// @is - "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.output.inner.lifetime" \"\'a\" +// @is "$.index[*][?(@.name=='ForAll')].kind" \"typedef\" +// @count "$.index[*][?(@.name=='ForAll')].inner.generics.params[*]" 0 +// @count "$.index[*][?(@.name=='ForAll')].inner.generics.where_predicates[*]" 0 +// @count "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*]" 1 +// @is "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].name" \"\'a\" +// @has "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].kind.lifetime" +// @count "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].kind.lifetime.outlives[*]" 0 +// @count "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.inputs[*]" 1 +// @is "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.inputs[*][1].inner.lifetime" \"\'a\" +// @is "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.output.inner.lifetime" \"\'a\" pub type ForAll = for<'a> fn(&'a i32) -> &'a i32; diff --git a/src/test/rustdoc-json/type/generic_default.rs b/src/test/rustdoc-json/type/generic_default.rs index b6bb6dcc5fe..9c6d4540bfb 100644 --- a/src/test/rustdoc-json/type/generic_default.rs +++ b/src/test/rustdoc-json/type/generic_default.rs @@ -1,33 +1,33 @@ // ignore-tidy-linelength -// @set result = generic_default.json "$.index[*][?(@.name=='Result')].id" +// @set result = "$.index[*][?(@.name=='Result')].id" pub enum Result { Ok(T), Err(E), } -// @set my_error = - "$.index[*][?(@.name=='MyError')].id" +// @set my_error = "$.index[*][?(@.name=='MyError')].id" pub struct MyError {} -// @is - "$.index[*][?(@.name=='MyResult')].kind" \"typedef\" -// @count - "$.index[*][?(@.name=='MyResult')].inner.generics.where_predicates[*]" 0 -// @count - "$.index[*][?(@.name=='MyResult')].inner.generics.params[*]" 2 -// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].name" \"T\" -// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].name" \"E\" -// @has - "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type" -// @has - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type" -// @count - "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type.bounds[*]" 0 -// @count - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.bounds[*]" 0 -// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type.default" null -// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.kind" \"resolved_path\" -// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.inner.id" $my_error -// @is - "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.inner.name" \"MyError\" -// @is - "$.index[*][?(@.name=='MyResult')].inner.type.kind" \"resolved_path\" -// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.id" $result -// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.name" \"Result\" -// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.bindings" [] -// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"generic\" -// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[1].type.kind" \"generic\" -// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[0].type.inner" \"T\" -// @is - "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[1].type.inner" \"E\" +// @is "$.index[*][?(@.name=='MyResult')].kind" \"typedef\" +// @count "$.index[*][?(@.name=='MyResult')].inner.generics.where_predicates[*]" 0 +// @count "$.index[*][?(@.name=='MyResult')].inner.generics.params[*]" 2 +// @is "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].name" \"T\" +// @is "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].name" \"E\" +// @has "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type" +// @has "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type" +// @count "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type.bounds[*]" 0 +// @count "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.bounds[*]" 0 +// @is "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type.default" null +// @is "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.kind" \"resolved_path\" +// @is "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.inner.id" $my_error +// @is "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.inner.name" \"MyError\" +// @is "$.index[*][?(@.name=='MyResult')].inner.type.kind" \"resolved_path\" +// @is "$.index[*][?(@.name=='MyResult')].inner.type.inner.id" $result +// @is "$.index[*][?(@.name=='MyResult')].inner.type.inner.name" \"Result\" +// @is "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.bindings" [] +// @is "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"generic\" +// @is "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[1].type.kind" \"generic\" +// @is "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[0].type.inner" \"T\" +// @is "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[1].type.inner" \"E\" pub type MyResult = Result; diff --git a/src/test/rustdoc-json/type/hrtb.rs b/src/test/rustdoc-json/type/hrtb.rs index 5b0c4caee21..2c4ee00d468 100644 --- a/src/test/rustdoc-json/type/hrtb.rs +++ b/src/test/rustdoc-json/type/hrtb.rs @@ -1,9 +1,7 @@ // ignore-tidy-linelength -// @has hrtb.json - -// @is - "$.index[*][?(@.name=='genfn')].inner.generics.where_predicates[0].bound_predicate.type" '{"inner": "F","kind": "generic"}' -// @is - "$.index[*][?(@.name=='genfn')].inner.generics.where_predicates[0].bound_predicate.generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]' +// @is "$.index[*][?(@.name=='genfn')].inner.generics.where_predicates[0].bound_predicate.type" '{"inner": "F","kind": "generic"}' +// @is "$.index[*][?(@.name=='genfn')].inner.generics.where_predicates[0].bound_predicate.generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]' pub fn genfn(f: F) where for<'a, 'b> F: Fn(&'a i32, &'b i32), @@ -12,14 +10,14 @@ where f(&zero, &zero); } -// @is - "$.index[*][?(@.name=='dynfn')].inner.generics" '{"params": [], "where_predicates": []}' -// @is - "$.index[*][?(@.name=='dynfn')].inner.generics" '{"params": [], "where_predicates": []}' -// @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].kind" '"borrowed_ref"' -// @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.kind" '"dyn_trait"' -// @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.lifetime" null -// @count - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[*]" 1 -// @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]' -// @is - "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[0].trait.name" '"Fn"' +// @is "$.index[*][?(@.name=='dynfn')].inner.generics" '{"params": [], "where_predicates": []}' +// @is "$.index[*][?(@.name=='dynfn')].inner.generics" '{"params": [], "where_predicates": []}' +// @is "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].kind" '"borrowed_ref"' +// @is "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.kind" '"dyn_trait"' +// @is "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.lifetime" null +// @count "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[*]" 1 +// @is "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]' +// @is "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[0].trait.name" '"Fn"' pub fn dynfn(f: &dyn for<'a, 'b> Fn(&'a i32, &'b i32)) { let zero = 0; f(&zero, &zero); diff --git a/src/test/rustdoc-json/unions/impl.rs b/src/test/rustdoc-json/unions/impl.rs index 0388b4a8c3c..8dfbbfc1bae 100644 --- a/src/test/rustdoc-json/unions/impl.rs +++ b/src/test/rustdoc-json/unions/impl.rs @@ -1,15 +1,15 @@ #![no_std] -// @has impl.json "$.index[*][?(@.name=='Ux')].visibility" \"public\" -// @has - "$.index[*][?(@.name=='Ux')].kind" \"union\" +// @has "$.index[*][?(@.name=='Ux')].visibility" \"public\" +// @has "$.index[*][?(@.name=='Ux')].kind" \"union\" pub union Ux { a: u32, b: u64 } -// @has - "$.index[*][?(@.name=='Num')].visibility" \"public\" -// @has - "$.index[*][?(@.name=='Num')].kind" \"trait\" +// @has "$.index[*][?(@.name=='Num')].visibility" \"public\" +// @has "$.index[*][?(@.name=='Num')].kind" \"trait\" pub trait Num {} -// @count - "$.index[*][?(@.name=='Ux')].inner.impls" 1 +// @count "$.index[*][?(@.name=='Ux')].inner.impls" 1 impl Num for Ux {} diff --git a/src/test/rustdoc-json/unions/union.rs b/src/test/rustdoc-json/unions/union.rs index ac2eb797791..5467f68477f 100644 --- a/src/test/rustdoc-json/unions/union.rs +++ b/src/test/rustdoc-json/unions/union.rs @@ -1,6 +1,6 @@ -// @has union.json "$.index[*][?(@.name=='Union')].visibility" \"public\" -// @has - "$.index[*][?(@.name=='Union')].kind" \"union\" -// @!has - "$.index[*][?(@.name=='Union')].inner.struct_type" +// @has "$.index[*][?(@.name=='Union')].visibility" \"public\" +// @has "$.index[*][?(@.name=='Union')].kind" \"union\" +// @!has "$.index[*][?(@.name=='Union')].inner.struct_type" pub union Union { int: i32, float: f32, -- cgit 1.4.1-3-g733a5 From ac70aea98509c33ec75208f7b42c8d905c74ebaf Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 11 Aug 2022 15:52:29 +0100 Subject: Address reviewer comments Signed-off-by: Nick Cameron --- library/std/src/fs.rs | 4 +- library/std/src/io/buffered/bufreader.rs | 4 +- library/std/src/io/buffered/bufreader/buffer.rs | 2 +- library/std/src/io/copy.rs | 2 +- library/std/src/io/cursor.rs | 4 +- library/std/src/io/impls.rs | 8 +-- library/std/src/io/mod.rs | 16 +++--- library/std/src/io/readbuf.rs | 65 ++++++++++++++++--------- library/std/src/io/readbuf/tests.rs | 4 +- library/std/src/io/util.rs | 4 +- library/std/src/sys/hermit/fs.rs | 2 +- library/std/src/sys/solid/fs.rs | 2 +- library/std/src/sys/unix/fd.rs | 2 +- library/std/src/sys/unix/fs.rs | 2 +- library/std/src/sys/unsupported/fs.rs | 2 +- library/std/src/sys/wasi/fs.rs | 2 +- library/std/src/sys/windows/fs.rs | 2 +- library/std/src/sys/windows/handle.rs | 2 +- 18 files changed, 74 insertions(+), 55 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 98aa40db321..e1ab06b0d0f 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -703,7 +703,7 @@ impl Read for File { self.inner.read_vectored(bufs) } - fn read_buf(&mut self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { self.inner.read_buf(cursor) } @@ -755,7 +755,7 @@ impl Read for &File { self.inner.read(buf) } - fn read_buf(&mut self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { self.inner.read_buf(cursor) } diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index dced922ea57..88ad92d8a98 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -266,7 +266,7 @@ impl Read for BufReader { Ok(nread) } - fn read_buf(&mut self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> { // If we don't have any buffered data and we're doing a massive read // (larger than our internal buffer), bypass our internal buffer // entirely. @@ -278,7 +278,7 @@ impl Read for BufReader { let prev = cursor.written(); let mut rem = self.fill_buf()?; - rem.read_buf(cursor.clone())?; + rem.read_buf(cursor.reborrow())?; self.consume(cursor.written() - prev); //slice impl of read_buf known to never unfill buf diff --git a/library/std/src/io/buffered/bufreader/buffer.rs b/library/std/src/io/buffered/bufreader/buffer.rs index b122a6c0ccc..867c22c6041 100644 --- a/library/std/src/io/buffered/bufreader/buffer.rs +++ b/library/std/src/io/buffered/bufreader/buffer.rs @@ -93,7 +93,7 @@ impl Buffer { if self.pos >= self.filled { debug_assert!(self.pos == self.filled); - let mut buf: BorrowedBuf<'_> = (&mut *self.buf).into(); + let mut buf = BorrowedBuf::from(&mut *self.buf); // SAFETY: `self.filled` bytes will always have been initialized. unsafe { buf.set_init(self.filled); diff --git a/library/std/src/io/copy.rs b/library/std/src/io/copy.rs index 1efd98b92aa..38b98afffa1 100644 --- a/library/std/src/io/copy.rs +++ b/library/std/src/io/copy.rs @@ -106,7 +106,7 @@ impl BufferedCopySpec for BufWriter { if read_buf.capacity() >= DEFAULT_BUF_SIZE { let mut cursor = read_buf.unfilled(); - match reader.read_buf(cursor.clone()) { + match reader.read_buf(cursor.reborrow()) { Ok(()) => { let bytes_read = cursor.written(); diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index e00577b5107..d98ab021cad 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -323,10 +323,10 @@ where Ok(n) } - fn read_buf(&mut self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> { let prev_written = cursor.written(); - Read::read_buf(&mut self.fill_buf()?, cursor.clone())?; + Read::read_buf(&mut self.fill_buf()?, cursor.reborrow())?; self.pos += (cursor.written() - prev_written) as u64; diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index 183c8c660b4..e5048dcc8ac 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -21,7 +21,7 @@ impl Read for &mut R { } #[inline] - fn read_buf(&mut self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { (**self).read_buf(cursor) } @@ -125,7 +125,7 @@ impl Read for Box { } #[inline] - fn read_buf(&mut self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { (**self).read_buf(cursor) } @@ -249,7 +249,7 @@ impl Read for &[u8] { } #[inline] - fn read_buf(&mut self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> { let amt = cmp::min(cursor.capacity(), self.len()); let (a, b) = self.split_at(amt); @@ -427,7 +427,7 @@ impl Read for VecDeque { } #[inline] - fn read_buf(&mut self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { let (ref mut front, _) = self.as_slices(); let n = cmp::min(cursor.capacity(), front.len()); Read::read_buf(front, cursor)?; diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 02f82a7e995..8b8ec32bf5b 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -370,7 +370,7 @@ pub(crate) fn default_read_to_end(r: &mut R, buf: &mut Vec } let mut cursor = read_buf.unfilled(); - match r.read_buf(cursor.clone()) { + match r.read_buf(cursor.reborrow()) { Ok(()) => {} Err(e) if e.kind() == ErrorKind::Interrupted => continue, Err(e) => return Err(e), @@ -462,7 +462,7 @@ pub(crate) fn default_read_exact(this: &mut R, mut buf: &mut [ } } -pub(crate) fn default_read_buf(read: F, mut cursor: BorrowedCursor<'_, '_>) -> Result<()> +pub(crate) fn default_read_buf(read: F, mut cursor: BorrowedCursor<'_>) -> Result<()> where F: FnOnce(&mut [u8]) -> Result, { @@ -812,7 +812,7 @@ pub trait Read { /// /// The default implementation delegates to `read`. #[unstable(feature = "read_buf", issue = "78485")] - fn read_buf(&mut self, buf: BorrowedCursor<'_, '_>) -> Result<()> { + fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<()> { default_read_buf(|b| self.read(b), buf) } @@ -821,10 +821,10 @@ pub trait Read { /// This is equivalent to the [`read_exact`](Read::read_exact) method, except that it is passed a [`BorrowedCursor`] rather than `[u8]` to /// allow use with uninitialized buffers. #[unstable(feature = "read_buf", issue = "78485")] - fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_, '_>) -> Result<()> { + fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_>) -> Result<()> { while cursor.capacity() > 0 { let prev_written = cursor.written(); - match self.read_buf(cursor.clone()) { + match self.read_buf(cursor.reborrow()) { Ok(()) => {} Err(e) if e.kind() == ErrorKind::Interrupted => continue, Err(e) => return Err(e), @@ -2586,7 +2586,7 @@ impl Read for Take { Ok(n) } - fn read_buf(&mut self, mut buf: BorrowedCursor<'_, '_>) -> Result<()> { + fn read_buf(&mut self, mut buf: BorrowedCursor<'_>) -> Result<()> { // Don't call into inner reader at all at EOF because it may still block if self.limit == 0 { return Ok(()); @@ -2609,7 +2609,7 @@ impl Read for Take { } let mut cursor = sliced_buf.unfilled(); - self.inner.read_buf(cursor.clone())?; + self.inner.read_buf(cursor.reborrow())?; let new_init = cursor.init_ref().len(); let filled = sliced_buf.len(); @@ -2626,7 +2626,7 @@ impl Read for Take { self.limit -= filled as u64; } else { let written = buf.written(); - self.inner.read_buf(buf.clone())?; + self.inner.read_buf(buf.reborrow())?; self.limit -= (buf.written() - written) as u64; } diff --git a/library/std/src/io/readbuf.rs b/library/std/src/io/readbuf.rs index ae3fbcc6a2f..b1a84095f13 100644 --- a/library/std/src/io/readbuf.rs +++ b/library/std/src/io/readbuf.rs @@ -6,7 +6,7 @@ mod tests; use crate::cmp; use crate::fmt::{self, Debug, Formatter}; use crate::io::{Result, Write}; -use crate::mem::MaybeUninit; +use crate::mem::{self, MaybeUninit}; /// A borrowed byte buffer which is incrementally filled and initialized. /// @@ -23,9 +23,9 @@ use crate::mem::MaybeUninit; /// ``` /// /// A `BorrowedBuf` is created around some existing data (or capacity for data) via a unique reference -/// (`&mut`). The `BorrowedBuf` can be configured (e.g., using `clear` or `set_init`), but otherwise -/// is read-only. To write into the buffer, use `unfilled` to create a `BorrowedCursor`. The cursor -/// has write-only access to the unfilled portion of the buffer (you can think of it like a +/// (`&mut`). The `BorrowedBuf` can be configured (e.g., using `clear` or `set_init`), but cannot be +/// directly written. To write into the buffer, use `unfilled` to create a `BorrowedCursor`. The cursor +/// has write-only access to the unfilled portion of the buffer (you can think of it as a /// write-only iterator). /// /// The lifetime `'data` is a bound on the lifetime of the underlying data. @@ -55,7 +55,7 @@ impl<'data> From<&'data mut [u8]> for BorrowedBuf<'data> { let len = slice.len(); BorrowedBuf { - //SAFETY: initialized data never becoming uninitialized is an invariant of BorrowedBuf + // SAFETY: initialized data never becoming uninitialized is an invariant of BorrowedBuf buf: unsafe { (slice as *mut [u8]).as_uninit_slice_mut().unwrap() }, filled: 0, init: len, @@ -95,14 +95,21 @@ impl<'data> BorrowedBuf<'data> { /// Returns a shared reference to the filled portion of the buffer. #[inline] pub fn filled(&self) -> &[u8] { - //SAFETY: We only slice the filled part of the buffer, which is always valid + // SAFETY: We only slice the filled part of the buffer, which is always valid unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[0..self.filled]) } } /// Returns a cursor over the unfilled part of the buffer. #[inline] - pub fn unfilled<'this>(&'this mut self) -> BorrowedCursor<'this, 'data> { - BorrowedCursor { start: self.filled, buf: self } + pub fn unfilled<'this>(&'this mut self) -> BorrowedCursor<'this> { + BorrowedCursor { + start: self.filled, + // SAFETY: we never assign into `BorrowedCursor::buf`, so treating its + // lifetime covariantly is safe. + buf: unsafe { + mem::transmute::<&'this mut BorrowedBuf<'data>, &'this mut BorrowedBuf<'this>>(self) + }, + } } /// Clears the buffer, resetting the filled region to empty. @@ -141,25 +148,37 @@ impl<'data> BorrowedBuf<'data> { /// `BorrowedBuf` and can no longer be accessed or re-written by the cursor. I.e., the cursor tracks /// the unfilled part of the underlying `BorrowedBuf`. /// -/// The `'buf` lifetime is a bound on the lifetime of the underlying buffer. `'data` is a bound on -/// that buffer's underlying data. +/// The lifetime `'a` is a bound on the lifetime of the underlying buffer (which means it is a bound +/// on the data in that buffer by transitivity). #[derive(Debug)] -pub struct BorrowedCursor<'buf, 'data> { +pub struct BorrowedCursor<'a> { /// The underlying buffer. - buf: &'buf mut BorrowedBuf<'data>, + // Safety invariant: we treat the type of buf as covariant in the lifetime of `BorrowedBuf` when + // we create a `BorrowedCursor`. This is only safe if we never replace `buf` by assigning into + // it, so don't do that! + buf: &'a mut BorrowedBuf<'a>, /// The length of the filled portion of the underlying buffer at the time of the cursor's /// creation. start: usize, } -impl<'buf, 'data> BorrowedCursor<'buf, 'data> { - /// Clone this cursor. +impl<'a> BorrowedCursor<'a> { + /// Reborrow this cursor by cloning it with a smaller lifetime. /// - /// Since a cursor maintains unique access to its underlying buffer, the cloned cursor is not - /// accessible while the clone is alive. + /// Since a cursor maintains unique access to its underlying buffer, the borrowed cursor is + /// not accessible while the new cursor exists. #[inline] - pub fn clone<'this>(&'this mut self) -> BorrowedCursor<'this, 'data> { - BorrowedCursor { buf: self.buf, start: self.start } + pub fn reborrow<'this>(&'this mut self) -> BorrowedCursor<'this> { + BorrowedCursor { + // SAFETY: we never assign into `BorrowedCursor::buf`, so treating its + // lifetime covariantly is safe. + buf: unsafe { + mem::transmute::<&'this mut BorrowedBuf<'a>, &'this mut BorrowedBuf<'this>>( + self.buf, + ) + }, + start: self.start, + } } /// Returns the available space in the cursor. @@ -170,8 +189,8 @@ impl<'buf, 'data> BorrowedCursor<'buf, 'data> { /// Returns the number of bytes written to this cursor since it was created from a `BorrowedBuf`. /// - /// Note that if this cursor is a clone of another, then the count returned is the count written - /// via either cursor, not the count since the cursor was cloned. + /// Note that if this cursor is a reborrowed clone of another, then the count returned is the + /// count written via either cursor, not the count since the cursor was reborrowed. #[inline] pub fn written(&self) -> usize { self.buf.filled - self.start @@ -180,14 +199,14 @@ impl<'buf, 'data> BorrowedCursor<'buf, 'data> { /// Returns a shared reference to the initialized portion of the cursor. #[inline] pub fn init_ref(&self) -> &[u8] { - //SAFETY: We only slice the initialized part of the buffer, which is always valid + // SAFETY: We only slice the initialized part of the buffer, which is always valid unsafe { MaybeUninit::slice_assume_init_ref(&self.buf.buf[self.buf.filled..self.buf.init]) } } /// Returns a mutable reference to the initialized portion of the cursor. #[inline] pub fn init_mut(&mut self) -> &mut [u8] { - //SAFETY: We only slice the initialized part of the buffer, which is always valid + // SAFETY: We only slice the initialized part of the buffer, which is always valid unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf.buf[self.buf.filled..self.buf.init]) } @@ -275,7 +294,7 @@ impl<'buf, 'data> BorrowedCursor<'buf, 'data> { } } -impl<'buf, 'data> Write for BorrowedCursor<'buf, 'data> { +impl<'a> Write for BorrowedCursor<'a> { fn write(&mut self, buf: &[u8]) -> Result { self.append(buf); Ok(buf.len()) diff --git a/library/std/src/io/readbuf/tests.rs b/library/std/src/io/readbuf/tests.rs index 8037a957908..cc1b423f2dd 100644 --- a/library/std/src/io/readbuf/tests.rs +++ b/library/std/src/io/readbuf/tests.rs @@ -117,14 +117,14 @@ fn append() { } #[test] -fn clone_written() { +fn reborrow_written() { let buf: &mut [_] = &mut [MaybeUninit::new(0); 32]; let mut buf: BorrowedBuf<'_> = buf.into(); let mut cursor = buf.unfilled(); cursor.append(&[1; 16]); - let mut cursor2 = cursor.clone(); + let mut cursor2 = cursor.reborrow(); cursor2.append(&[2; 16]); assert_eq!(cursor2.written(), 32); diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index 7475d71119a..f076ee0923c 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -47,7 +47,7 @@ impl Read for Empty { } #[inline] - fn read_buf(&mut self, _cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, _cursor: BorrowedCursor<'_>) -> io::Result<()> { Ok(()) } } @@ -130,7 +130,7 @@ impl Read for Repeat { Ok(buf.len()) } - fn read_buf(&mut self, mut buf: BorrowedCursor<'_, '_>) -> io::Result<()> { + fn read_buf(&mut self, mut buf: BorrowedCursor<'_>) -> io::Result<()> { // SAFETY: No uninit bytes are being written for slot in unsafe { buf.as_mut() } { slot.write(self.byte); diff --git a/library/std/src/sys/hermit/fs.rs b/library/std/src/sys/hermit/fs.rs index 51321c51972..1c5efa94bd3 100644 --- a/library/std/src/sys/hermit/fs.rs +++ b/library/std/src/sys/hermit/fs.rs @@ -312,7 +312,7 @@ impl File { false } - pub fn read_buf(&self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> { crate::io::default_read_buf(|buf| self.read(buf), cursor) } diff --git a/library/std/src/sys/solid/fs.rs b/library/std/src/sys/solid/fs.rs index 0848d3d8f10..8e23a7c7d88 100644 --- a/library/std/src/sys/solid/fs.rs +++ b/library/std/src/sys/solid/fs.rs @@ -358,7 +358,7 @@ impl File { } } - pub fn read_buf(&self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + pub fn read_buf(&self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> { unsafe { let len = cursor.capacity(); let mut out_num_bytes = MaybeUninit::uninit(); diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs index 76a269bb9b5..dbaa3c33e2e 100644 --- a/library/std/src/sys/unix/fd.rs +++ b/library/std/src/sys/unix/fd.rs @@ -131,7 +131,7 @@ impl FileDesc { } } - pub fn read_buf(&self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + pub fn read_buf(&self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> { let ret = cvt(unsafe { libc::read( self.as_raw_fd(), diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 50561345442..b8fc2e8da2b 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1031,7 +1031,7 @@ impl File { self.0.read_at(buf, offset) } - pub fn read_buf(&self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> { self.0.read_buf(cursor) } diff --git a/library/std/src/sys/unsupported/fs.rs b/library/std/src/sys/unsupported/fs.rs index 41e39ce27ce..6ac1b5d2bcf 100644 --- a/library/std/src/sys/unsupported/fs.rs +++ b/library/std/src/sys/unsupported/fs.rs @@ -214,7 +214,7 @@ impl File { self.0 } - pub fn read_buf(&self, _cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + pub fn read_buf(&self, _cursor: BorrowedCursor<'_>) -> io::Result<()> { self.0 } diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index b5b5eab1a24..510cf36b1bf 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -439,7 +439,7 @@ impl File { true } - pub fn read_buf(&self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> { crate::io::default_read_buf(|buf| self.read(buf), cursor) } diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index bfc2477dff4..9ac7cfebbeb 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -415,7 +415,7 @@ impl File { self.handle.read_at(buf, offset) } - pub fn read_buf(&self, cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> { self.handle.read_buf(cursor) } diff --git a/library/std/src/sys/windows/handle.rs b/library/std/src/sys/windows/handle.rs index 0ea6876af5b..ae33d48c612 100644 --- a/library/std/src/sys/windows/handle.rs +++ b/library/std/src/sys/windows/handle.rs @@ -112,7 +112,7 @@ impl Handle { } } - pub fn read_buf(&self, mut cursor: BorrowedCursor<'_, '_>) -> io::Result<()> { + pub fn read_buf(&self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> { let res = unsafe { self.synchronous_read(cursor.as_mut().as_mut_ptr(), cursor.capacity(), None) }; -- cgit 1.4.1-3-g733a5 From 00fec76ab53896c37eb584bc567d9a06865d0e17 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Wed, 17 Aug 2022 11:35:17 +0200 Subject: tidy: check fluent files for style --- compiler/rustc_error_messages/locales/en-US/borrowck.ftl | 4 ++-- compiler/rustc_error_messages/locales/en-US/expand.ftl | 6 +++--- src/tools/tidy/src/style.rs | 15 ++++++--------- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl index 4af40d2062d..93224f843fb 100644 --- a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl +++ b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl @@ -13,6 +13,6 @@ borrowck_could_not_normalize = borrowck_higher_ranked_subtype_error = higher-ranked subtype error - + generic_does_not_live_long_enough = - `{$kind}` does not live long enough \ No newline at end of file + `{$kind}` does not live long enough diff --git a/compiler/rustc_error_messages/locales/en-US/expand.ftl b/compiler/rustc_error_messages/locales/en-US/expand.ftl index ee76a4f4500..5720591154f 100644 --- a/compiler/rustc_error_messages/locales/en-US/expand.ftl +++ b/compiler/rustc_error_messages/locales/en-US/expand.ftl @@ -4,10 +4,10 @@ expand_explain_doc_comment_outer = expand_explain_doc_comment_inner = inner doc comments expand to `#![doc = "..."]`, which is what this macro attempted to match -expand_expr_repeat_no_syntax_vars = +expand_expr_repeat_no_syntax_vars = attempted to repeat an expression containing no syntax variables matched as repeating at this depth -expand_must_repeat_once = +expand_must_repeat_once = this must repeat at least once expand_count_repetition_misplaced = @@ -19,4 +19,4 @@ expand_meta_var_expr_unrecognized_var = expand_var_still_repeating = variable '{$ident}' is still repeating at this depth -expand_meta_var_dif_seq_matchers = {$msg} \ No newline at end of file +expand_meta_var_dif_seq_matchers = {$msg} diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 3cf44a2d7d1..dee58ff2fb5 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -125,16 +125,13 @@ fn should_ignore(line: &str) -> bool { /// Returns `true` if `line` is allowed to be longer than the normal limit. fn long_line_is_ok(extension: &str, is_error_code: bool, max_columns: usize, line: &str) -> bool { - if extension != "md" || is_error_code { - if line_is_url(is_error_code, max_columns, line) || should_ignore(line) { - return true; - } - } else if extension == "md" { + match extension { + // fluent files are allowed to be any length + "ftl" => true, // non-error code markdown is allowed to be any length - return true; + "md" if !is_error_code => true, + _ => line_is_url(is_error_code, max_columns, line) || should_ignore(line), } - - false } enum Directive { @@ -230,7 +227,7 @@ pub fn check(path: &Path, bad: &mut bool) { super::walk(path, &mut skip, &mut |entry, contents| { let file = entry.path(); let filename = file.file_name().unwrap().to_string_lossy(); - let extensions = [".rs", ".py", ".js", ".sh", ".c", ".cpp", ".h", ".md", ".css"]; + let extensions = [".rs", ".py", ".js", ".sh", ".c", ".cpp", ".h", ".md", ".css", ".ftl"]; if extensions.iter().all(|e| !filename.ends_with(e)) || filename.starts_with(".#") { return; } -- cgit 1.4.1-3-g733a5 From 295457192d100b62fa2c6148ad6b98b2b619937d Mon Sep 17 00:00:00 2001 From: Xiretza Date: Wed, 17 Aug 2022 11:45:35 +0200 Subject: fluent: fix slug name for borrowck::generic_does_not_live_long_enough --- compiler/rustc_error_messages/locales/en-US/borrowck.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl index 93224f843fb..a96fe7c8a05 100644 --- a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl +++ b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl @@ -14,5 +14,5 @@ borrowck_could_not_normalize = borrowck_higher_ranked_subtype_error = higher-ranked subtype error -generic_does_not_live_long_enough = +borrowck_generic_does_not_live_long_enough = `{$kind}` does not live long enough -- cgit 1.4.1-3-g733a5 From dac27679f75725c8a3e8ff5fc009f3bc59ce3523 Mon Sep 17 00:00:00 2001 From: Ryo Yoshida Date: Thu, 18 Aug 2022 08:46:06 +0900 Subject: fix: resolve path `Self` alone in value namespace --- crates/hir-ty/src/infer.rs | 1 + crates/hir-ty/src/tests/patterns.rs | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 46eeea0e6fc..7440439522e 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -734,6 +734,7 @@ impl<'a> InferenceContext<'a> { let ty = self.insert_type_vars(ty.substitute(Interner, &substs)); return (ty, Some(strukt.into())); } + ValueNs::ImplSelf(impl_id) => (TypeNs::SelfType(impl_id), None), _ => return (self.err_ty(), None), }, Some(ResolveValueResult::Partial(typens, unresolved)) => (typens, Some(unresolved)), diff --git a/crates/hir-ty/src/tests/patterns.rs b/crates/hir-ty/src/tests/patterns.rs index 94efe7bc11a..eb04bf87783 100644 --- a/crates/hir-ty/src/tests/patterns.rs +++ b/crates/hir-ty/src/tests/patterns.rs @@ -488,6 +488,42 @@ fn infer_adt_pattern() { ); } +#[test] +fn tuple_struct_destructured_with_self() { + check_infer( + r#" +struct Foo(usize,); +impl Foo { + fn f() { + let Self(s,) = &Foo(0,); + let Self(s,) = &mut Foo(0,); + let Self(s,) = Foo(0,); + } +} + "#, + expect![[r#" + 42..151 '{ ... }': () + 56..64 'Self(s,)': Foo + 61..62 's': &usize + 67..75 '&Foo(0,)': &Foo + 68..71 'Foo': Foo(usize) -> Foo + 68..75 'Foo(0,)': Foo + 72..73 '0': usize + 89..97 'Self(s,)': Foo + 94..95 's': &mut usize + 100..112 '&mut Foo(0,)': &mut Foo + 105..108 'Foo': Foo(usize) -> Foo + 105..112 'Foo(0,)': Foo + 109..110 '0': usize + 126..134 'Self(s,)': Foo + 131..132 's': usize + 137..140 'Foo': Foo(usize) -> Foo + 137..144 'Foo(0,)': Foo + 141..142 '0': usize + "#]], + ); +} + #[test] fn enum_variant_through_self_in_pattern() { check_infer( -- cgit 1.4.1-3-g733a5 From af4f66ef938bd21b82a81473974cb620be9a0c72 Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Thu, 18 Aug 2022 08:14:21 -0400 Subject: ADD - ExpectedUsedSymbol diagnostic to port used() diagnostic --- compiler/rustc_error_messages/locales/en-US/typeck.ftl | 2 ++ compiler/rustc_typeck/src/collect.rs | 7 +------ compiler/rustc_typeck/src/errors.rs | 7 +++++++ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/typeck.ftl b/compiler/rustc_error_messages/locales/en-US/typeck.ftl index 0014da17c88..d937661794a 100644 --- a/compiler/rustc_error_messages/locales/en-US/typeck.ftl +++ b/compiler/rustc_error_messages/locales/en-US/typeck.ftl @@ -131,3 +131,5 @@ typeck_unused_extern_crate = typeck_extern_crate_not_idiomatic = `extern crate` is not idiomatic in the new edition .suggestion = convert it to a `{$msg_code}` + +typeck_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)` diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index e7c5ecc60ec..970b39dc845 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2836,12 +2836,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED; } Some(_) => { - tcx.sess - .struct_span_err( - attr.span, - "expected `used`, `used(compiler)` or `used(linker)`", - ) - .emit(); + tcx.sess.emit_err(errors::ExpectedUsedSymbol { span: attr.span }); } None => { // Unfortunately, unconditionally using `llvm.used` causes diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs index 76599721e58..8b1cb8d1c93 100644 --- a/compiler/rustc_typeck/src/errors.rs +++ b/compiler/rustc_typeck/src/errors.rs @@ -340,3 +340,10 @@ pub struct ExternCrateNotIdiomatic { pub msg_code: String, pub suggestion_code: String, } + +#[derive(SessionDiagnostic)] +#[error(typeck::expected_used_symbol)] +pub struct ExpectedUsedSymbol { + #[primary_span] + pub span: Span, +} -- cgit 1.4.1-3-g733a5 From 5fc1366dfa0b5c9615be028e75f4f237f165831b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 18 Aug 2022 12:55:44 +0000 Subject: Register debuginfo for lazy jit shim --- src/driver/jit.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/driver/jit.rs b/src/driver/jit.rs index de71b76da4e..00e7263446b 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -140,7 +140,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { }); } CodegenMode::JitLazy => { - codegen_shim(tcx, &mut cached_context, &mut jit_module, inst) + codegen_shim(tcx, &mut cx, &mut cached_context, &mut jit_module, inst) } }, MonoItem::Static(def_id) => { @@ -353,6 +353,7 @@ fn load_imported_symbols_for_jit( fn codegen_shim<'tcx>( tcx: TyCtxt<'tcx>, + cx: &mut CodegenCx<'tcx>, cached_context: &mut Context, module: &mut JITModule, inst: Instance<'tcx>, @@ -403,4 +404,5 @@ fn codegen_shim<'tcx>( trampoline_builder.ins().return_(&ret_vals); module.define_function(func_id, context).unwrap(); + cx.unwind_context.add_function(func_id, context, module.isa()); } -- cgit 1.4.1-3-g733a5 From 88e3d752e42842a8a5db75d17e44973f72ce14f8 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 18 Aug 2022 15:32:45 +0200 Subject: import the debian/copyright file from debian MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Angus Lees Co-Authored-By: Fabian Grünbichler Co-Authored-By: Hiroaki Nakamura Co-Authored-By: Jordan Justen Co-Authored-By: Luca Bruno Co-Authored-By: Sylvestre Ledru Co-Authored-By: Ximin Luo --- .reuse/dep5 | 2164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 2159 insertions(+), 5 deletions(-) diff --git a/.reuse/dep5 b/.reuse/dep5 index 03d9f152d5f..0afbe833746 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -1,7 +1,2161 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: rust +Source: https://www.rust-lang.org +Files-Excluded: + *.min.js + src/llvm-emscripten + src/llvm-project +# Fonts already in Debian, covered by d-rustdoc-use-system-font.patch +# TODO make that patch, modify src/librustdoc/html/static/css/rustdoc.css + src/librustdoc/html/static/fonts/noto-sans-* +# Pre-generated docs + src/tools/rustfmt/docs +# Proprietary doc formats + src/doc/book/nostarch/docx +# Fonts already in Debian, covered by d-0003-mdbook-strip-embedded-libs.patch + vendor/mdbook/src/theme/fonts + vendor/mdbook/src/theme/FontAwesome + vendor/mdbook/src/theme/highlight.js + vendor/mdbook/src/theme/highlight.css +# Exclude submodules https://github.com/rust-lang/rust/tree/master/src/tools +# We prefer to do them in different Debian packages so they can have their own +# version numbers. If upstream merges them "properly" (i.e. unify the version +# numbers) then we can merge the packages in Debian. Note that cargotest here +# does actually belong to rustc, it is an integration test suite for rustc to +# check that certain popular crates continue to compile. It is not the same as +# cargo's own test suite (in its own package) also called cargotest. +# NB: don't exclude rust-installer, it's needed for "install" functionality + src/tools/cargo + src/tools/rls + src/tools/remote-test-client + src/tools/remote-test-server + src/tools/rust-analyzer + src/tools/miri +# Embedded GH pages + src/tools/clippy/util/gh-pages +# Misc embedded + vendor/structopt/link-check-headers.json +# Embedded C libraries + vendor/libz-sys/src/zlib* + vendor/lzma-sys*/xz-* +# Embedded binary blobs + vendor/jsonpath_lib/docs + vendor/mdbook/src/theme/playground_editor + vendor/psm/src/arch/wasm32.o + vendor/winapi-*/*/*.a +# Embedded submodule used for CI + library/stdarch/crates/intrinsic-test/acle +# NPM packages we can't be bothered documenting licenses for + vendor/tera/docs/node_modules +# unused dependencies, generated by debian/prune-unused-deps +# DO NOT EDIT below, AUTOGENERATED + vendor/addr2line + vendor/adler-0.2.3 + vendor/always-assert + vendor/anymap + vendor/arbitrary + vendor/ar + vendor/arrayvec-0.7.0 + vendor/autocfg-1.0.0 + vendor/backtrace + vendor/bitflags-1.2.1 + vendor/bitmaps + vendor/bytes + vendor/bytesize + vendor/cargo_metadata-0.14.0 + vendor/cc-1.0.69 + vendor/chalk-recursive + vendor/commoncrypto + vendor/commoncrypto-sys + vendor/core-foundation + vendor/core-foundation-sys + vendor/countme + vendor/cov-mark + vendor/cranelift-bforest + vendor/cranelift-codegen + vendor/cranelift-codegen-meta + vendor/cranelift-codegen-shared + vendor/cranelift-entity + vendor/cranelift-frontend + vendor/cranelift-jit + vendor/cranelift-module + vendor/cranelift-native + vendor/cranelift-object + vendor/crc32fast-1.2.0 + vendor/crossbeam-channel-0.5.0 + vendor/crossbeam-utils-0.8.3 + vendor/crypto-hash + vendor/curl + vendor/curl-sys + vendor/dashmap + vendor/derive_arbitrary + vendor/derive_more + vendor/directories + vendor/dot + vendor/drop_bomb + vendor/either-1.6.0 + vendor/enum-iterator + vendor/enum-iterator-derive + vendor/env_logger + vendor/expect-test-1.0.1 + vendor/filetime-0.2.14 + vendor/flate2-1.0.16 + vendor/foreign-types + vendor/foreign-types-shared + vendor/fsevent-sys + vendor/fs_extra-1.1.0 + vendor/fs_extra + vendor/fst-0.4.5 + vendor/fst + vendor/futures-0.1.29 + vendor/futures + vendor/futures-channel + vendor/futures-core + vendor/futures-executor + vendor/futures-io + vendor/futures-macro + vendor/futures-sink + vendor/futures-task + vendor/futures-util + vendor/fwdansi + vendor/getset + vendor/git2 + vendor/git2-curl + vendor/hashbrown-0.11.0 + vendor/heck-0.3.1 + vendor/hex-0.3.2 + vendor/home + vendor/idna-0.1.5 + vendor/idna-0.2.0 + vendor/im-rc + vendor/inotify + vendor/inotify-sys + vendor/itertools-0.10.1 + vendor/itoa-0.4.6 + vendor/jod-thread + vendor/json + vendor/jsonrpc-client-transports + vendor/jsonrpc-core + vendor/jsonrpc-core-client + vendor/jsonrpc-derive + vendor/jsonrpc-ipc-server + vendor/jsonrpc-pubsub + vendor/jsonrpc-server-utils + vendor/kqueue + vendor/kqueue-sys + vendor/lazycell + vendor/libc-0.2.108 + vendor/libgit2-sys + vendor/libloading-0.6.7 + vendor/libloading-0.7.1 + vendor/libmimalloc-sys + vendor/libnghttp2-sys + vendor/libssh2-sys + vendor/libz-sys + vendor/linked-hash-map + vendor/lsp-codec + vendor/lsp-server + vendor/lsp-types-0.60.0 + vendor/lsp-types + vendor/mach + vendor/matches-0.1.8 + vendor/measureme-9.1.2 + vendor/memmap2 + vendor/mimalloc + vendor/miniz_oxide-0.4.0 + vendor/mio-0.7.13 + vendor/mio + vendor/miow + vendor/notify + vendor/ntapi + vendor/object + vendor/once_cell-1.7.2 + vendor/oorandom + vendor/openssl + vendor/openssl-probe + vendor/openssl-src + vendor/openssl-sys + vendor/ordslice + vendor/os_info + vendor/parity-tokio-ipc + vendor/paste + vendor/percent-encoding-1.0.1 + vendor/perf-event + vendor/pin-project-lite-0.2.4 + vendor/pin-utils + vendor/pretty_env_logger + vendor/proc-macro2-1.0.30 + vendor/proc-macro-crate + vendor/proc-macro-hack + vendor/proc-macro-nested + vendor/pulldown-cmark-0.8.0 + vendor/pulldown-cmark-to-cmark + vendor/quote-1.0.7 + vendor/racer + vendor/rand_xoshiro-0.4.0 + vendor/rayon-1.3.1 + vendor/rayon-core-1.7.1 + vendor/regalloc + vendor/region + vendor/rls-vfs + vendor/rowan + vendor/rustc-ap-rustc_arena + vendor/rustc-ap-rustc_ast + vendor/rustc-ap-rustc_ast_pretty + vendor/rustc-ap-rustc_data_structures + vendor/rustc-ap-rustc_errors + vendor/rustc-ap-rustc_feature + vendor/rustc-ap-rustc_fs_util + vendor/rustc-ap-rustc_graphviz + vendor/rustc-ap-rustc_index + vendor/rustc-ap-rustc_lexer-722.0.0 + vendor/rustc-ap-rustc_lexer + vendor/rustc-ap-rustc_lint_defs + vendor/rustc-ap-rustc_macros + vendor/rustc-ap-rustc_parse + vendor/rustc-ap-rustc_serialize + vendor/rustc-ap-rustc_session + vendor/rustc-ap-rustc_span + vendor/rustc-ap-rustc_target + vendor/rustc_version + vendor/ryu-1.0.5 + vendor/salsa + vendor/salsa-macros + vendor/schannel + vendor/security-framework + vendor/security-framework-sys + vendor/semver-1.0.3 + vendor/serde-1.0.125 + vendor/serde_derive-1.0.125 + vendor/serde_ignored + vendor/serde_json-1.0.59 + vendor/serde_repr-0.1.6 + vendor/serde_repr + vendor/sharded-slab-0.1.1 + vendor/signal-hook-registry + vendor/sized-chunks + vendor/slab + vendor/smol_str + vendor/snap-1.0.1 + vendor/socket2 + vendor/strip-ansi-escapes + vendor/syn-1.0.80 + vendor/target-lexicon + vendor/text-size + vendor/thread_local-1.0.1 + vendor/threadpool + vendor/tikv-jemallocator + vendor/tikv-jemalloc-ctl + vendor/tikv-jemalloc-sys-0.4.1+5.2.1-patched + vendor/tikv-jemalloc-sys + vendor/tinyvec-0.3.4 + vendor/tokio + vendor/tokio-stream + vendor/tokio-util + vendor/tower-service + vendor/typed-arena + vendor/ungrammar + vendor/unicode-bidi-0.3.4 + vendor/unicode-normalization-0.1.13 + vendor/unicode-segmentation-1.6.0 + vendor/url-1.7.2 + vendor/utf8parse + vendor/vcpkg + vendor/vergen + vendor/vte + vendor/walkdir-2.3.1 + vendor/windows_aarch64_msvc + vendor/windows_i686_gnu + vendor/windows_i686_msvc + vendor/windows-sys + vendor/windows_x86_64_gnu + vendor/windows_x86_64_msvc + vendor/write-json + vendor/xflags + vendor/xflags-macros + vendor/xshell + vendor/xshell-macros + vendor/yaml-merge-keys + vendor/yaml-rust +# DO NOT EDIT above, AUTOGENERATED -# Temporarily mark all files to be licensed with the custom "TODO" license, -# until we import the proper licensing metadata in a separate PR. -Files: * -Copyright: TODO -License: LicenseRef-TODO +Files: C*.md + R*.md + Cargo.lock + Cargo.toml + COPYRIGHT + LICENSE* + compiler/* + configure + config.toml.example + git-commit-hash + library/* + src/README.md + src/bootstrap/* + src/build_helper/* + src/ci/* + src/doc/* + src/etc/* + src/lib* + src/rust* + src/stage0.json + src/tools/* + src/test/* + src/version + version + x.py +Copyright: 2006-2009 Graydon Hoare + 2009-2012 Mozilla Foundation + 2012-2017 The Rust Project Developers (see AUTHORS.txt) +License: MIT or Apache-2.0 + +Files: library/std/src/sync/mpsc/mpsc_queue.rs + library/std/src/sync/mpsc/spsc_queue.rs +Copyright: 2010-2011 Dmitry Vyukov +License: BSD-2-Clause + +Files: src/librustdoc/html/static/fonts/FiraSans* +Copyright: 2014, Mozilla Foundation, 2014, Telefonica S.A. +License: SIL-OPEN-FONT + +Files: src/librustdoc/html/static/fonts/NanumBarun* +Copyright: 2010 NAVER Corporation +License: SIL-OPEN-FONT + +Files: src/librustdoc/html/static/fonts/SourceCodePro* +Copyright: 2010, 2012 Adobe Systems Incorporated +License: SIL-OPEN-FONT + +Files: src/librustdoc/html/static/fonts/SourceSerif4* +Copyright: 2014-2021 Adobe Systems Incorporated +License: SIL-OPEN-FONT + +Files: vendor/compiler_builtins/* +Copyright: 2016-2019 Jorge Aparicio +License: MIT or Apache-2.0 +Comment: see https://github.com/rust-lang-nursery/compiler-builtins + +Files: vendor/compiletest_rs/* +Copyright: 2015-2020 The Rust Project Developers + 2015-2020 Thomas Bracht Laumann Jespersen + 2015-2020 Manish Goregaokar +License: Apache-2.0 or MIT +Comment: see https://github.com/laumann/compiletest-rs + +Files: + vendor/bitflags/* + vendor/cc/* + vendor/cmake/* + vendor/env_logger-0*/* + vendor/getopts/* + vendor/glob/* + vendor/libc/* + vendor/log/* + vendor/regex/* + vendor/regex-syntax/* + vendor/rustc-hash/* + vendor/time/* +Copyright: 2010-2021 The Rust Project Developers +License: MIT or Apache-2.0 +Comment: + This is a collection of external crates embedded here to bootstrap cargo. + Most of them come from the original upstream Rust project, thus share the + same MIT/Apache-2.0 dual-license. See https://github.com/rust-lang. + Exceptions are noted below. + +Files: vendor/num-integer/* + vendor/num-traits/* +Copyright: 2014-2018 The Rust Project Developers +License: MIT or Apache-2.0 +Comment: see https://github.com/rust-num/num + +Files: + vendor/string_cache/* + vendor/string_cache_codegen/* + vendor/unicode-bidi/* +Copyright: 2015-2017 Alex Crichton + 2015-2017 Keegan McAllister + 2015-2017 Chris Morgan + 2014-2017 The html5ever Project Developers + 2014-2017 The Servo Project Developers + 2013-2017 Simon Sapin +License: MIT or Apache-2.0 +Comment: see https://github.com/servo/ + +Files: + vendor/getrandom/* + vendor/getrandom-0*/* + vendor/rand/* + vendor/rand-0*/* + vendor/rand_chacha/* + vendor/rand_chacha-0*/* + vendor/rand_core/* + vendor/rand_core-0*/* + vendor/rand_hc/* + vendor/rand_hc-0*/* + vendor/rand_pcg/* + vendor/rand_xorshift/* + vendor/rand_xoshiro/* +Copyright: 2010-2019 The Rand Project Developers + 2010-2019 The Rust Project Developers +License: MIT or Apache-2.0 +Comment: + see https://github.com/rust-random/getrandom + see https://github.com/rust-random/rand + see https://github.com/rust-random/small-rngs + +Files: + vendor/cfg-if-0*/* + vendor/cfg-if/* + vendor/filetime/* + vendor/flate2/* + vendor/fnv/* + vendor/jobserver/* + vendor/lzma-sys/* + vendor/pkg-config/* + vendor/proc-macro2/* + vendor/rustc-demangle/* + vendor/scoped-tls/* + vendor/tar/* + vendor/toml/* + vendor/xz2/* +Copyright: 2014-2020 Alex Crichton + 2015-2017 The Rust Project Developers +License: MIT or Apache-2.0 +Comment: see https://github.com/alexcrichton/ + +Files: vendor/dlmalloc/* +Copyright: 2017-2019 Alex Crichton +License: MIT or Apache-2.0 +Comment: see https://github.com/alexcrichton/dlmalloc-rs + +Files: vendor/dlmalloc/src/dlmalloc.c +Copyright: 2000-2012 Doug Lea +License: CC0-1.0 + +Files: vendor/tester/* +Copyright: 2016-2019 The Rust Project Developers +License: MIT OR Apache-2.0 +Comment: see https://github.com/messense/rustc-test + +Files: vendor/addr2line-0*/* +Copyright: + 2016-2021 Nick Fitzgerald + 2016-2021 Philip Craig + 2016-2021 Jon Gjengset + 2016-2021 Noah Bergbauer +License: Apache-2.0 or MIT +Comment: see https://github.com/gimli-rs/addr2line + +Files: vendor/adler/* +Copyright: 2020-2020 Jonas Schievink +License: 0BSD or MIT or Apache-2.0 +Comment: see https://github.com/jonas-schievink/adler.git + +Files: vendor/ammonia/* +Copyright: 2015-2018 Michael Howell +License: MIT or Apache-2.0 +Comment: see https://github.com/notriddle/ammonia + +Files: vendor/annotate-snippets/* +Copyright: 2018-2020 Zibi Braniecki +License: Apache-2.0 or MIT +Comment: see https://github.com/zbraniecki/annotate-snippets-rs + +Files: + vendor/ansi_term/* + vendor/ansi_term-0*/* +Copyright: + 2014-2020 ogham@bsago.me + 2014-2020 Ryan Scheel (Havvy) + 2014-2020 Josh Triplett +License: MIT +Comment: see https://github.com/ogham/rust-ansi-term + +Files: vendor/aho-corasick/* + vendor/memchr/* +Copyright: 2015 Andrew Gallant + 2015-2018 bluss +License: MIT or Unlicense +Comment: see upstream projects, + * https://github.com/BurntSushi/aho-corasick + * https://github.com/BurntSushi/rust-memchr + +Files: vendor/array_tool/* +Copyright: 2015-2018 Daniel P. Clark <6ftdan@gmail.com> +License: MIT OR Apache-2.0 +Comment: see https://github.com/danielpclark/array_tool + +Files: vendor/autocfg/* +Copyright: 2018-2020 Josh Stone +License: Apache-2.0 or MIT + +Files: vendor/atty/* +Copyright: 2015-2017 softprops +License: MIT +Comment: see https://github.com/softprops/atty + +Files: + vendor/block-buffer/* + vendor/block-buffer-0*/* + vendor/block-padding/* + vendor/byte-tools/* + vendor/cpuid-bool/* + vendor/digest/* + vendor/digest-0*/* + vendor/fake-simd/* + vendor/md-5/* + vendor/opaque-debug/* + vendor/opaque-debug-0*/* + vendor/sha-1-0*/* + vendor/sha-1/* + vendor/sha2/* +Copyright: 2016-2020 RustCrypto Developers +License: MIT or Apache-2.0 +Comment: + see https://github.com/RustCrypto/hashes + see https://github.com/RustCrypto/traits + see https://github.com/RustCrypto/utils + +Files: vendor/bstr/* +Copyright: 2018-2020 Andrew Gallant +License: MIT OR Apache-2.0 +Comment: see https://github.com/BurntSushi/bstr + +Files: vendor/bytecount/* +Copyright: 2016-2020 Andre Bogus + 2016-2020 Joshua Landau +License: Apache-2.0 or MIT +Comment: see https://github.com/llogiq/bytecount + +Files: + vendor/byteorder/* + vendor/globset/* + vendor/ignore/* + vendor/same-file/* + vendor/termcolor/* + vendor/walkdir/* + vendor/winapi-util/* +Copyright: 2015-2020 Andrew Gallant +License: Unlicense or MIT +Comment: + see https://github.com/BurntSushi/byteorder + see https://github.com/BurntSushi/same-file + see https://github.com/BurntSushi/walkdir + see https://github.com/BurntSushi/winapi-util + see https://github.com/BurntSushi/ripgrep/tree/master/globset + see https://github.com/BurntSushi/ripgrep/tree/master/ignore + see https://github.com/BurntSushi/ripgrep/tree/master/termcolor + +Files: vendor/camino/* +Copyright: 2020-2022 Without Boats + 2020-2022 Ashley Williams + 2020-2022 Steve Klabnik + 2020-2022 Rain +License: MIT OR Apache-2.0 +Comment: see https://github.com/withoutboats/camino + +Files: + vendor/cargo_metadata/* + vendor/cargo_metadata-0*/* +Copyright: 2016-2020 Oliver Schneider +License: MIT +Comment: + see https://github.com/oli-obk/cargo_metadata + +Files: vendor/cargo-platform/* +Copyright: 2019-2022 The Cargo Project Developers +License: MIT OR Apache-2.0 +Comment: see https://github.com/rust-lang/cargo + +Files: vendor/ppv-lite86/* +Copyright: 2019-2019 The CryptoCorrosion Contributors +License: MIT or Apache-2.0 +Comment: see https://github.com/cryptocorrosion/cryptocorrosion + +Files: + vendor/chalk-derive/* + vendor/chalk-engine/* + vendor/chalk-ir/* + vendor/chalk-solve/* +Copyright: + 2015-2022 Rust Compiler Team + 2015-2022 Chalk developers +License: Apache-2.0 or MIT +Comment: see https://github.com/rust-lang/chalk + +Files: vendor/chrono/* +Copyright: 2014-2018 Kang Seonghoon +License: MIT or Apache-2.0 +Comment: see https://github.com/chronotope/chrono + +Files: vendor/clap/* +Copyright: 2015-2017 Kevin K. +License: MIT +Comment: see https://github.com/kbknapp/clap-rs.git + +Files: vendor/colored/* +Copyright: 2016-2020 Thomas Wickham +License: MPL-2.0 +Comment: see https://github.com/mackwic/colored + +Files: vendor/crc32fast/* +Copyright: 2018-2019 Sam Rijs + 2018-2019 Alex Crichton +License: MIT OR Apache-2.0 +Comment: see https://github.com/srijs/rust-crc32fast + +Files: + vendor/crossbeam-channel/* + vendor/crossbeam-deque/* + vendor/crossbeam-deque-0*/* + vendor/crossbeam-epoch/* + vendor/crossbeam-epoch-0*/* + vendor/crossbeam-queue/* + vendor/crossbeam-utils/* + vendor/crossbeam-utils-0*/* +Copyright: 2015-2021 The Crossbeam Project Developers +License: MIT or Apache-2.0 +Comment: see https://github.com/crossbeam-rs + +Files: vendor/cstr/* +Copyright: 2018-2020 Xidorn Quan +License: MIT +Comment: see https://github.com/upsuper/cstr + +Files: vendor/ctor/* +Copyright: 2018-2020 Matt Mastracci +License: Apache-2.0 OR MIT +Comment: see https://github.com/mmastrac/rust-ctor + +Files: vendor/datafrog/* +Copyright: + 2018 Frank McSherry + 2018 The Rust Project Developers + 2018 Datafrog Developers +License: Apache-2.0 or MIT +Comment: see https://github.com/rust-lang-nursery/datafrog + +Files: vendor/derive-new/* +Copyright: 2016-2020 Nick Cameron +License: MIT +Comment: see https://github.com/nrc/derive-new + +Files: vendor/diff/* +Copyright: 2015-2017 Utkarsh Kukreti +License: MIT or Apache-2.0 +Comment: see https://github.com/utkarshkukreti/diff.rs + +Files: + vendor/anyhow/* + vendor/dissimilar/* + vendor/itoa/* + vendor/quote/* + vendor/syn/* +Copyright: 2016-2022 David Tolnay +License: MIT or Apache-2.0 +Comment: + see https://github.com/dtolnay/anyhow + see https://github.com/dtolnay/dissimilar + see https://github.com/dtolnay/itoa + see https://github.com/dtolnay/quote + see https://github.com/dtolnay/syn + +Files: + vendor/arrayvec/* + vendor/either/* + vendor/fixedbitset/* + vendor/itertools/* + vendor/itertools-0*/* + vendor/maplit/* + vendor/scopeguard/* +Copyright: 2014-2020 bluss +License: MIT or Apache-2.0 +Comment: + see https://github.com/bluss/rust-itertools + see https://github.com/bluss/either + see https://github.com/bluss/arrayvec + see https://github.com/bluss/fixedbitset + see https://github.com/bluss/maplit + see https://github.com/bluss/scopeguard + +Files: vendor/difference/* +Copyright: 2015-2018 Johann Hofmann +License: MIT +Comment: see https://github.com/johannhof/difference.rs + +Files: + vendor/dirs/* + vendor/dirs-sys/* +Copyright: 2015-2020 Simon Ochsenreither + 2015-2020 dirs-rs contributors +License: MIT OR Apache-2.0 +Comment: + see https://github.com/dirs-dev/dirs-rs + see https://github.com/dirs-dev/dirs-sys-rs + +Files: + vendor/dirs-next/* + vendor/dirs-sys-next/* +Copyright: 2017-2021 The @xdg-rs members +License: MIT OR Apache-2.0 +Comment: see https://github.com/xdg-rs/dirs + +Files: vendor/elasticlunr-rs/* +Copyright: 2017-2018 Matt Ickstadt +License: MIT or Apache-2.0 +Comment: see https://github.com/mattico/elasticlunr-rs + +Files: vendor/ena/* +Copyright: 2015-2020 Niko Matsakis +License: MIT or Apache-2.0 +Comment: see https://github.com/nikomatsakis/ena + +Files: vendor/expect-test/* +Copyright: 2020-2022 rust-analyzer developers +License: MIT OR Apache-2.0 +Comment: see https://github.com/rust-analyzer/expect-test + +Files: vendor/fallible-iterator/* +Copyright: 2016-2019 Steven Fackler +License: MIT or Apache-2.0 +Comment: see https://github.com/sfackler/rust-fallible-iterator + +Files: vendor/fortanix-sgx-abi/* +Copyright: 2015-2019 Jethro Beekman +License: MPL-2.0 +Comment: see https://github.com/fortanix/rust-sgx + +Files: vendor/fs-err/* +Copyright: 2020-2020 Andrew Hickman +License: MIT or Apache-2.0 +Comment: see https://github.com/andrewhickman/fs-err + +Files: vendor/futf/* +Copyright: 2015-2018 Keegan McAllister +License: MIT or Apache-2.0 +Comment: see https://github.com/servo/futf + +Files: + vendor/generic-array/* + vendor/generic-array-0*/* +Copyright: + 2015-2020 Bartłomiej Kamiński + 2015-2020 Aaron Trent +License: MIT +Comment: see https://github.com/fizyk20/generic-array.git + +Files: + vendor/gimli-0*/* + vendor/gimli/* +Copyright: + 2016-2021 Nick Fitzgerald + 2016-2021 Philip Craig +License: Apache-2.0 or MIT +Comment: see https://github.com/gimli-rs/gimli + +Files: vendor/globwalk/* +Copyright: 2018-2020 Gilad Naaman +License: MIT +Comment: see https://github.com/gilnaa/globwalk + +Files: vendor/gsgdt/* +Copyright: 2020 Vishnunarayan K I +License: MIT or Apache-2.0 +Comment: see https://github.com/vn-ki/gsgdt-rs + +Files: vendor/handlebars/* +Copyright: 2014-2017 Ning Sun +License: MIT +Comment: see https://github.com/sunng87/handlebars-rust + +Files: vendor/heck/* +Copyright: 2017-2018 Without Boats +License: MIT OR Apache-2.0 +Comment: see https://github.com/withoutboats/heck + +Files: vendor/hermit-abi/* +Copyright: 2019-2019 Stefan Lankes +License: MIT or Apache-2.0 +Comment: see https://github.com/hermitcore/hermit-abi + +Files: vendor/hex/* +Copyright: 2015-2020 KokaKiwi +License: MIT OR Apache-2.0 +Comment: see https://github.com/KokaKiwi/rust-hex + +Files: + vendor/html5ever/* + vendor/markup5ever/* + vendor/markup5ever_rcdom/* +Copyright: 2014-2020 The html5ever Project Developers +License: MIT or Apache-2.0 +Comment: see https://github.com/servo/html5ever + +Files: + vendor/humantime/* + vendor/humantime-*/* +Copyright: + 2016-2018 Paul Colomiets + 2016 The humantime Developers + 2016 Pyfisch + 2005-2013 Rich Felker +License: MIT or Apache-2.0 + +Files: vendor/if_chain/* +Copyright: 2016-2020 Chris Wong +License: MIT or Apache-2.0 +Comment: see https://github.com/lfairy/if_chain + +Files: + vendor/form_urlencoded/* + vendor/idna/* + vendor/percent-encoding/* + vendor/url/* +Copyright: 2013-2021 The rust-url developers +License: MIT or Apache-2.0 +Comment: see https://github.com/servo/rust-url/ + +Files: vendor/indexmap/* +Copyright: 2016-2019 bluss + 2016-2019 Josh Stone +License: Apache-2.0 or MIT +Comment: see https://github.com/bluss/indexmap + +Files: + vendor/indoc/* + vendor/unindent/* +Copyright: 2016-2022 David Tolnay +License: MIT OR Apache-2.0 +Comment: see https://github.com/dtolnay/indoc + +Files: vendor/instant/* +Copyright: 2019-2020 sebcrozet +License: BSD-3-Clause +Comment: see https://github.com/sebcrozet/instant + +Files: vendor/jsonpath_lib/* +Copyright: 2018-2021 Changseok Han +License: MIT +Comment: see https://github.com/freestrings/jsonpath + +Files: vendor/lazy_static/* +Copyright: 2014-2018 Marvin Löbel +License: MIT or Apache-2.0 +Comment: + see https://github.com/rust-lang-nursery/lazy-static.rs + see https://github.com/Kimundi/owning-ref-rs + +Files: vendor/libloading/* +Copyright: 2015-2022 Simonas Kazlauskas +License: ISC +Comment: see https://github.com/nagisa/rust_libloading/ + +Files: vendor/libm/* +Copyright: 2018-2021 Jorge Aparicio +License: MIT OR Apache-2.0 +Comment: see https://github.com/rust-lang-nursery/libm + +Files: vendor/mac/* +Copyright: 2014-2017 Jonathan Reem +License: MIT +Comment: + see https://github.com/reem/rust-mac.git + +Files: vendor/matchers/* +Copyright: 2019-2019 Eliza Weisman +License: MIT +Comment: see https://github.com/hawkw/matchers + +Files: vendor/matches/* +Copyright: 2014-2017 Simon Sapin +License: MIT +Comment: see https://github.com/SimonSapin + +Files: vendor/maybe-uninit/* +Copyright: 2019-2019 est31 + 2019-2019 The Rust Project Developers +License: Apache-2.0 OR MIT +Comment: see https://github.com/est31/maybe-uninit + +Files: vendor/mdbook/* +Copyright: 2015-2017 Mathieu David +License: MPL-2.0 +Comment: see https://github.com/azerupi/mdBook + +Files: vendor/measureme/* +Copyright: 2019-2020 Wesley Wiser + 2019-2020 Michael Woerister +License: MIT OR Apache-2.0 +Comment: see https://github.com/rust-lang/measureme + +Files: vendor/memmap2-0*/* +Copyright: 2015-2021 Dan Burkert + 2015-2021 Evgeniy Reizner +License: MIT or Apache-2.0 +Comment: see https://github.com/RazrFalcon/memmap2-rs + +Files: + vendor/memoffset/* + vendor/memoffset-0*/* +Copyright: 2017-2019 Gilad Naaman +License: MIT +Comment: see https://github.com/Gilnaa/memoffset + +Files: + vendor/macro-utils/* + vendor/minifier/* +Copyright: 2017-2018 Guillaume Gomez +License: MIT +Comment: + see https://github.com/GuillaumeGomez/macro_utils + see https://github.com/GuillaumeGomez/minifier-rs + +Files: + vendor/miniz_oxide/* +Copyright: 2017-2020 Frommi +License: MIT +Comment: see https://github.com/Frommi/miniz_oxide + +Files: vendor/miow-0.3.7/* +Copyright: 2014-2021 Alex Crichton +License: MIT or Apache-2.0 +Comment: see https://github.com/yoshuawuyts/miow + +Files: vendor/new_debug_unreachable/* +Copyright: 2014-2018 Matt Brubeck + 2014-2018 Jonathan Reem +License: MIT +Comment: see https://github.com/mbrubeck/rust-debug-unreachable + +Files: vendor/num_cpus/* +Copyright: 2015 Sean McArthur +License: MIT +Comment: see https://github.com/seanmonstar/num_cpus + +Files: vendor/object-0*/* +Copyright: + 2016-2020 Nick Fitzgerald + 2016-2020 Philip Craig +License: Apache-2.0 or MIT +Comment: see https://github.com/gimli-rs/object + +Files: vendor/odht/* +Copyright: 2021 Michael Woerister +License: Apache-2.0 or MIT +Comment: see https://github.com/rust-lang/odht + +Files: vendor/opener/* +Copyright: 2018-2020 Brian Bowman +License: MIT OR Apache-2.0 +Comment: see https://github.com/Seeker14491/opener + +Files: vendor/once_cell/* +Copyright: 2018-2019 Aleksey Kladov +License: MIT OR Apache-2.0 +Comment: see https://github.com/matklad/once_cell + +Files: vendor/output_vt100/* +Copyright: 2019-2019 Phuntsok Drak-pa +License: MIT +Comment: see https://github.com/Phundrak/output-vt100-rs + +Files: + vendor/hashbrown/* + vendor/lock_api/* + vendor/thread_local/* + vendor/parking_lot/* + vendor/parking_lot_core/* +Copyright: 2016-2019 Amanieu d'Antras +License: MIT or Apache-2.0 +Comment: + see https://github.com/rust-lang/hashbrown + see https://github.com/Amanieu/thread_local-rs + see https://github.com/Amanieu/parking_lot + +Files: vendor/packed_simd_2/* +Copyright: 2018-2021 Gonzalo Brito Gadeschi + 2018-2021 Jubilee Young +License: MIT or Apache-2.0 +Comment: see https://github.com/rust-lang-nursery/packed_simd + +Files: vendor/pathdiff/* +Copyright: 2017-2020 Manish Goregaokar +License: MIT or Apache-2.0 +Comment: see https://github.com/Manishearth/pathdiff + +Files: vendor/perf-event-open-sys/* +Copyright: 2019-2020 Jim Blandy +License: MIT OR Apache-2.0 +Comment: see https://github.com/jimblandy/perf-event.git + +Files: + vendor/pest/* + vendor/pest_derive/* + vendor/pest_generator/* + vendor/pest_meta/* +Copyright: 2016-2019 Dragoș Tiselice +License: MIT or Apache-2.0 +Comment: + see https://github.com/dragostis/pest + see https://github.com/pest-parser/pest + +Files: vendor/polonius-engine/* +Copyright: 2018-2018 The Rust Project Developers + 2018-2018 Polonius Developers +License: Apache-2.0 or MIT +Comment: see https://github.com/rust-lang-nursery/polonius + +Files: vendor/petgraph/* +Copyright: 2014-2018 bluss + 2014-2018 mitchmindtree +License: MIT or Apache-2.0 +Comment: see https://github.com/bluss/petgraph + +Files: + vendor/phf/* + vendor/phf_codegen/* + vendor/phf_generator/* + vendor/phf_shared/* +Copyright: 2014-2018 Steven Fackler +License: MIT +Comment: see https://github.com/sfackler/rust-phf + +Files: vendor/pin-project-lite/* +Copyright: 2018-2021 Taiki Endo +License: Apache-2.0 or MIT +Comment: + see https://github.com/taiki-e/pin-project-lite + +Files: vendor/precomputed-hash/* +Copyright: 2017-2017 Emilio Cobos Álvarez +License: MIT +Comment: see https://github.com/emilio/precomputed-hash + +Files: vendor/pretty_assertions/* +Copyright: 2017-2018 Colin Kiegel + 2017-2018 Florent Fayolle +License: MIT or Apache-2.0 +Comment: see https://github.com/colin-kiegel/rust-pretty-assertions + +Files: + vendor/proc-macro-error/* + vendor/proc-macro-error-attr/* +Copyright: 2019-2020 CreepySkeleton +License: MIT OR Apache-2.0 +Comment: see https://gitlab.com/CreepySkeleton/proc-macro-error + +Files: vendor/psm/* +Copyright: 2015-2020 Simonas Kazlauskas +License: MIT or Apache-2.0 +Comment: see https://github.com/rust-lang/stacker/ + +Files: vendor/pulldown-cmark/* +Copyright: 2015-2017 Raph Levien +License: MIT +Comment: see https://github.com/google/pulldown-cmark + +Files: vendor/punycode/* +Copyright: 2015-2019 mcarton +License: MIT +Comment: see https://github.com/mcarton/rust-punycode.git + +Files: + vendor/quick-error/* + vendor/quick-error-1*/* +Copyright: + 2015-2020 Paul Colomiets + 2015-2020 Colin Kiegel +License: MIT or Apache-2.0 +Comment: see http://github.com/tailhook/quick-error + +Files: vendor/quine-mc_cluskey/* +Copyright: 2016-2016 Oliver Schneider +License: MIT +Comment: see https://github.com/oli-obk/quine-mc_cluskey + +Files: + vendor/rayon/* + vendor/rayon-core/* + vendor/rustc-rayon/* + vendor/rustc-rayon-core/* +Copyright: 2014-2018 Niko Matsakis + 2014-2018 Josh Stone +License: Apache-2.0 or MIT +Comment: + see https://github.com/rayon-rs/rayon + see https://github.com/Zoxc/rayon/tree/rustc + +Files: vendor/redox_users/* +Copyright: 2017-2021 Jose Narvaez + 2017-2021 Wesley Hershberger +License: MIT +Comment: see https://gitlab.redox-os.org/redox-os/users + +Files: vendor/redox_syscall/* +Copyright: 2016-2021 Jeremy Soller +License: MIT +Comment: + see https://github.com/redox-os/syscall + +Files: vendor/regex-automata/* +Copyright: 2018-2020 Andrew Gallant +License: Unlicense or MIT +Comment: see https://github.com/BurntSushi/regex-automata + +Files: vendor/remove_dir_all/* +Copyright: 2017-2018 Aaronepower +License: MIT or Apache-2.0 +Comment: see https://github.com/Aaronepower/remove_dir_all.git + +Files: vendor/rls-data/* + vendor/rls-span/* +Copyright: 2016-2017 Nick Cameron +License: Apache-2.0 or MIT +Comment: see https://github.com/nrc/rls-span + see https://github.com/nrc/rls-data + +Files: vendor/rustc-semver/* +Copyright: 2020-2020 flip1995 +License: MIT OR Apache-2.0 +Comment: see https://github.com/flip1995/rustc-semver + +Files: vendor/rustc_tools_util/* +Copyright: 2014-2021 Matthias Krüger +License: MIT or Apache-2.0 +Comment: see https://github.com/rust-lang/rust-clippy + +Files: + vendor/rustfix/* + vendor/rustfix-0*/* +Copyright: + 2016-2021 Pascal Hertleif + 2016-2021 Oliver Schneider +License: Apache-2.0 or MIT +Comment: see https://github.com/killercup/rustfix + +Files: vendor/rustversion/* +Copyright: 2019-2021 David Tolnay +License: MIT OR Apache-2.0 +Comment: see https://github.com/dtolnay/rustversion + +Files: vendor/ryu/* +Copyright: 2018-2018 David Tolnay +License: Apache-2.0 or BSL-1.0 +Comment: see https://github.com/dtolnay/ryu + +Files: + vendor/semver-0*/* + vendor/semver/* + vendor/semver-parser/* +Copyright: + 2014-2020 Steve Klabnik + 2014-2020 The Rust Project Developers +License: MIT or Apache-2.0 +Comment: + see https://github.com/steveklabnik/semver + see https://github.com/steveklabnik/semver-parser + +Files: vendor/serde/* + vendor/serde_json/* +Copyright: 2014-2017 Erick Tryzelaar +License: MIT or Apache-2.0 +Comment: + see https://github.com/serde-rs/serde + see https://github.com/serde-rs/json + +Files: vendor/serde_derive/* +Copyright: 2014-2017 Erick Tryzelaar + 2016-2017 David Tolnay +License: MIT or Apache-2.0 +Comment: see https://github.com/serde-rs/serde + +Files: vendor/sharded-slab/* +Copyright: 2019-2020 Eliza Weisman +License: MIT +Comment: see https://github.com/hawkw/sharded-slab + +Files: vendor/shell-escape/* +Copyright: 2016-2020 Steven Fackler +License: MIT or Apache-2.0 +Comment: see https://github.com/sfackler/shell-escape + +Files: vendor/shlex/* +Copyright: 2015-2015 comex +License: MIT or Apache-2.0 +Comment: see https://github.com/comex/rust-shlex + +Files: vendor/siphasher/* +Copyright: 2016-2018 Frank Denis +License: MIT or Apache-2.0 +Comment: see https://github.com/jedisct1/rust-siphash + +Files: vendor/smallvec/* +Copyright: 2015-2020 Simon Sapin +License: MPL-2.0 +Comment: see https://github.com/servo/rust-smallvec + +Files: vendor/snap/* +Copyright: 2016-2020 Andrew Gallant +License: BSD-3-Clause +Comment: see https://github.com/BurntSushi/rust-snappy + +Files: vendor/stable_deref_trait/* +Copyright: 2017-2017 Robert Grosse +License: MIT or Apache-2.0 +Comment: see https://github.com/storyyeller/stable_deref_trait + +Files: vendor/stacker/* +Copyright: 2015-2020 Alex Crichton + 2015-2020 Simonas Kazlauskas +License: MIT or Apache-2.0 +Comment: see https://github.com/rust-lang/stacker + +Files: vendor/strsim/* +Copyright: 2015 Danny Guo +License: MIT +Comment: see https://github.com/dguo/strsim-rs + +Files: + vendor/structopt/* + vendor/structopt-derive/* +Copyright: 2017-2020 Guillaume Pinot + 2017-2020 others +License: Apache-2.0 OR MIT +Comment: see https://github.com/TeXitoi/structopt + +Files: + vendor/strum/* + vendor/strum_macros/* +Copyright: 2015-2018 Peter Glotfelty +License: MIT + +Files: vendor/synstructure/* +Copyright: + 2016-2019 Nika Layzell +License: MIT +Comment: see https://github.com/mystor/synstructure + +Files: vendor/tempfile/* +Copyright: 2015-2018 Steven Allen + 2015-2018 The Rust Project Developers + 2015-2018 Ashley Mannix + 2015-2018 Jason White +License: MIT or Apache-2.0 +Comment: see https://github.com/Stebalien/tempfile + +Files: vendor/tendril/* +Copyright: 2015-2017 Keegan McAllister + 2015-2017 Simon Sapin + 2015-2017 Chris Morgan +License: MIT or Apache-2.0 +Comment: see https://github.com/servo/tendril + +Files: vendor/tera/* +Copyright: 2015-2021 Vincent Prouillet +License: MIT +Comment: see https://github.com/Keats/tera + +Files: + vendor/term/* + vendor/term-0*/* +Copyright: + 2014-2021 The Rust Project Developers + 2014-2021 Steven Allen +License: MIT or Apache-2.0 +Comment: see https://github.com/Stebalien/term + +Files: vendor/termize/* +Copyright: 2016-2020 Yuki Okushi +License: MIT or Apache-2.0 +Comment: see https://github.com/JohnTitor/termize + +Files: vendor/textwrap/* +Copyright: 2016-2017 Martin Geisler +License: MIT +Comment: see https://github.com/mgeisler/textwrap + +Files: + vendor/thiserror/* + vendor/thiserror-impl/* +Copyright: 2019-2020 David Tolnay +License: MIT OR Apache-2.0 +Comment: see https://github.com/dtolnay/thiserror + +Files: vendor/thorin-dwp/* +Copyright: 2021-2022 David Wood +License: MIT OR Apache-2.0 +Comment: see https://github.com/davidtwco/thorin + +Files: vendor/tinyvec/* +Copyright: 2020 Lokathor +License: Zlib +Comment: see https://github.com/Lokathor/tinyvec + +Files: vendor/tinyvec_macros/* +Copyright: 2020 Soveu +License: MIT or Apache-2.0 or Zlib +Comment: see https://github.com/Soveu/tinyvec_macros + +Files: vendor/topological-sort/* +Copyright: 2015-2018 gifnksm +License: MIT OR Apache-2.0 +Comment: see https://github.com/gifnksm/topological-sort-rs + +Files: + vendor/tracing/* + vendor/tracing-attributes/* + vendor/tracing-core/* + vendor/tracing-log/* + vendor/tracing-subscriber/* +Copyright: + 2018-2020 Eliza Weisman + 2018-2020 Tokio Contributors + 2018-2020 David Barsky +License: MIT +Comment: see https://github.com/tokio-rs/tracing + +Files: vendor/tracing-tree/* +Copyright: 2020-2020 David Barsky + 2020-2020 Nathan Whitaker +License: MIT OR Apache-2.0 +Comment: see https://github.com/davidbarsky/tracing-tree + +Files: vendor/typenum/* +Copyright: 2015-2019 Paho Lurie-Gregg + 2015-2019 Andre Bogus +License: MIT or Apache-2.0 +Comment: see https://github.com/paholg/typenum + +Files: vendor/version_check/* +Copyright: 2017-2019 Sergio Benitez +License: MIT or Apache-2.0 +Comment: see https://github.com/SergioBenitez/version_check + +Files: + vendor/ucd-parse/* + vendor/ucd-trie/* +Copyright: 2017-2020 Andrew Gallant +License: MIT or Apache-2.0 +Comment: + see https://github.com/BurntSushi/rucd + see https://github.com/BurntSushi/ucd-generate + +Files: vendor/unicase/* +Copyright: 2014-2019 Sean McArthur +License: MIT or Apache-2.0 +Comment: see https://github.com/seanmonstar/unicase + +Files: vendor/unicode_categories/* +Copyright: 2015-2016 Sean Gillespie +License: MIT OR Apache-2.0 +Comment: see https://github.com/swgillespie/unicode-categories + +Files: vendor/unic-*/* +Copyright: 2017-2022 The UNIC Project Developers +License: MIT or Apache-2.0 +Comment: see https://github.com/open-i18n/rust-unic/ + +Files: + vendor/unicode-normalization/* + vendor/unicode-segmentation/* + vendor/unicode-width/* +Copyright: 2015-2019 kwantam +License: MIT or Apache-2.0 +Comment: + see https://github.com/unicode-rs/unicode-normalization + see https://github.com/unicode-rs/unicode-segmentation + see https://github.com/unicode-rs/unicode-width + +Files: vendor/unicode-xid/* +Copyright: 2015-2017 erick.tryzelaar + 2015-2017 kwantam +License: MIT or Apache-2.0 +Comment: see https://github.com/unicode-rs/unicode-xid + +Files: vendor/unicode-script/* +Copyright: 2017-2020 Manish Goregaokar +License: MIT or Apache-2.0 +Comment: see https://github.com/unicode-rs/unicode-script + +Files: vendor/unicode-security/* +Copyright: 2020-2020 Charles Lew + 2020-2020 Manish Goregaokar +License: MIT or Apache-2.0 +Comment: see https://github.com/unicode-rs/unicode-security + +Files: vendor/unified-diff/* +Copyright: 2021-2021 Michael Howell + 2021-2021 The Rust Project Developers +License: MIT OR Apache-2.0 +Comment: see https://github.com/notriddle/rust-unified-diff + +Files: vendor/utf-8/* +Copyright: 2015-2018 Simon Sapin +License: MIT OR Apache-2.0 +Comment: see https://github.com/SimonSapin/rust-utf8 + +Files: vendor/vec_map/* +Copyright: 2015-2017 Alexis Beingessner + 2015-2017 Andrew Paseltiner + 2015-2017 contain-rs developers + 2015-2017 The Rust Project Developers +License: MIT or Apache-2.0 +Comment: see https://github.com/contain-rs/vec-map + +Files: vendor/wasi/* +Copyright: 2019-2020 The Cranelift Project Developers +License: Apache-2.0 with LLVM exception or Apache-2.0 or MIT +Comment: see https://github.com/CraneStation/rust-wasi + +Files: vendor/winapi/* +Copyright: + 2014-2019 Peter Atashian + 2014-2019 winapi-rs developers +License: MIT +Comment: see https://github.com/retep998/winapi-rs + +Files: vendor/winapi-*-pc-windows-gnu/* +Copyright: 2014-2018 Peter Atashian +License: MIT or Apache-2.0 +Comment: see https://github.com/retep998/winapi-rs + +Files: vendor/xattr/* +Copyright: 2015-2017 Steven Allen +License: MIT or Apache-2.0 +Comment: see https://github.com/Stebalien/xattr + +Files: vendor/xml5ever/* +Copyright: 2014-2020 The xml5ever project developers +License: MIT or Apache-2.0 +Comment: see https://github.com/servo/html5ever + +Files: vendor/yaml-rust-0*/* +Copyright: 2015-2020 Yuheng Chen +License: MIT or Apache-2.0 +Comment: see https://github.com/chyh1990/yaml-rust + +Files: vendor/yansi-term/* +Copyright: 2014-2020 ogham@bsago.me + 2014-2020 Ryan Scheel (Havvy) + 2014-2020 Josh Triplett + 2014-2020 Juan Aguilar Santillana +License: MIT +Comment: see https://github.com/botika/yansi-term + +Files: debian/* +Copyright: 2013-2018 Debian Rust Maintainers +License: MIT or Apache-2.0 + +Files: debian/icons/rust-logo-32x32-blk.png +Copyright: Mozilla Foundation +License: CC-BY +Comment: + Relevant discussion in https://github.com/rust-lang/rust/issues/11562 + +License: 0BSD + Permission to use, copy, modify, and/or distribute this software for + any purpose with or without fee is hereby granted. + . + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +License: Apache-2.0 + On Debian systems, the full text of the Apache License Version 2.0 + can be found in the file `/usr/share/common-licenses/Apache-2.0'. + +License: Apache-2.0 with LLVM exception + On Debian systems, the full text of the Apache License Version 2.0 + can be found in the file `/usr/share/common-licenses/Apache-2.0'. + Additionally, the LLVM exception is as follows: + . + As an exception, if, as a result of your compiling your source code, portions + of this Software are embedded into an Object form of such source code, you + may redistribute such embedded portions in such Object form without complying + with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + . + In addition, if you combine or link compiled forms of this Software with + software that is licensed under the GPLv2 ("Combined Software") and if a + court of competent jurisdiction determines that the patent provision (Section + 3), the indemnity provision (Section 9) or other Section of the License + conflicts with the conditions of the GPLv2, you may retroactively and + prospectively choose to deem waived or otherwise exclude such Section(s) of + the License, but only in their entirety and only with respect to the Combined + Software. + +License: BSD-2-clause + Redistribution and use in source and binary forms, with + or without modification, are permitted provided that the + following conditions are met: + . + 1. Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + 2. Redistributions in binary form must reproduce the + above copyright notice, this list of conditions and + the following disclaimer in the documentation and/or + other materials provided with the distribution. + . + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +License: CC0-1.0 + On Debian systems, the full text of the CC0 1.0 Universal + License can be found in the file + `/usr/share/common-licenses/CC0-1.0'. + +License: ISC + Permission to use, copy, modify, and/or distribute this software for any purpose + with or without fee is hereby granted, provided that the above copyright notice + and this permission notice appear in all copies. + . + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF + THIS SOFTWARE. + +License: MIT + Permission is hereby granted, free of charge, to any + person obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the + Software without restriction, including without + limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of + the Software, and to permit persons to whom the Software + is furnished to do so, subject to the following + conditions: + . + The above copyright notice and this permission notice + shall be included in all copies or substantial portions + of the Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF + ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + +License: BSL-1.0 + Permission is hereby granted, free of charge, to any person or organization + obtaining a copy of the software and accompanying documentation covered by + this license (the "Software") to use, reproduce, display, distribute, + execute, and transmit the Software, and to prepare derivative works of the + Software, and to permit third-parties to whom the Software is furnished to + do so, all subject to the following: + . + The copyright notices in the Software and this entire statement, including + the above license grant, this restriction and the following disclaimer, + must be included in all copies of the Software, in whole or in part, and + all derivative works of the Software, unless such copies or derivative + works are solely in the form of machine-executable object code generated by + a source language processor. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + +License: BSD-3-clause + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the organization nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + . + THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +License: Unlicense + This is free and unencumbered software released into the public domain. + . + Anyone is free to copy, modify, publish, use, compile, sell, or + distribute this software, either in source code form or as a compiled + binary, for any purpose, commercial or non-commercial, and by any + means. + . + In jurisdictions that recognize copyright laws, the author or authors + of this software dedicate any and all copyright interest in the + software to the public domain. We make this dedication for the + benefit of the public at large and to the detriment of our heirs and + successors. We intend this dedication to be an overt act of + relinquishment in perpetuity of all present and future rights to this + software under copyright law. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + . + For more information, please refer to + +License: SIL-OPEN-FONT + This Font Software is licensed under the SIL Open Font License, + Version 1.1. + . + This license is copied below, and is also available with a FAQ at: + http://scripts.sil.org/OFL + . + SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 + . + PREAMBLE The goals of the Open Font License (OFL) are to stimulate + worldwide development of collaborative font projects, to support the font + creation efforts of academic and linguistic communities, and to provide + a free and open framework in which fonts may be shared and improved in + partnership with others. + . + The OFL allows the licensed fonts to be used, studied, modified and + redistributed freely as long as they are not sold by themselves. + The fonts, including any derivative works, can be bundled, embedded, + redistributed and/or sold with any software provided that any reserved + names are not used by derivative works. The fonts and derivatives, + however, cannot be released under any other type of license. The + requirement for fonts to remain under this license does not apply to + any document created using the fonts or their derivatives. + . + DEFINITIONS + "Font Software" refers to the set of files released by the Copyright + Holder(s) under this license and clearly marked as such. + This may include source files, build scripts and documentation. + . + "Reserved Font Name" refers to any names specified as such after the + copyright statement(s). + . + "Original Version" refers to the collection of Font Software components + as distributed by the Copyright Holder(s). + . + "Modified Version" refers to any derivative made by adding to, deleting, + or substituting ? in part or in whole ? + any of the components of the Original Version, by changing formats or + by porting the Font Software to a new environment. + . + "Author" refers to any designer, engineer, programmer, technical writer + or other person who contributed to the Font Software. + . + PERMISSION & CONDITIONS + . + Permission is hereby granted, free of charge, to any person obtaining a + copy of the Font Software, to use, study, copy, merge, embed, modify, + redistribute, and sell modified and unmodified copies of the Font + Software, subject to the following conditions: + . + 1) Neither the Font Software nor any of its individual components,in + Original or Modified Versions, may be sold by itself. + . + 2) Original or Modified Versions of the Font Software may be bundled, + redistributed and/or sold with any software, provided that each copy + contains the above copyright notice and this license. These can be + included either as stand-alone text files, human-readable headers or + in the appropriate machine-readable metadata fields within text or + binary files as long as those fields can be easily viewed by the user. + . + 3) No Modified Version of the Font Software may use the Reserved Font + Name(s) unless explicit written permission is granted by the + corresponding Copyright Holder. This restriction only applies to the + primary font name as presented to the users. + . + 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font + Software shall not be used to promote, endorse or advertise any + Modified Version, except to acknowledge the contribution(s) of the + Copyright Holder(s) and the Author(s) or with their explicit written + permission. + 5) The Font Software, modified or unmodified, in part or in whole, must + be distributed entirely under this license, and must not be distributed + under any other license. The requirement for fonts to remain under + this license does not apply to any document created using the Font + Software. + . + TERMINATION + This license becomes null and void if any of the above conditions are not met. + . + DISCLAIMER + THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE + COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL + DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF THE USE OR INABILITY + +License: GPL-2+ + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + . + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + . + On Debian systems, see /usr/share/common-licenses/GPL-2 for the full + text of the GPL version 2. + +License: CC-BY + Attribution 4.0 International + . + ======================================================================= + . + Creative Commons Corporation ("Creative Commons") is not a law firm and + does not provide legal services or legal advice. Distribution of + Creative Commons public licenses does not create a lawyer-client or + other relationship. Creative Commons makes its licenses and related + information available on an "as-is" basis. Creative Commons gives no + warranties regarding its licenses, any material licensed under their + terms and conditions, or any related information. Creative Commons + disclaims all liability for damages resulting from their use to the + fullest extent possible. + . + Using Creative Commons Public Licenses + . + Creative Commons public licenses provide a standard set of terms and + conditions that creators and other rights holders may use to share + original works of authorship and other material subject to copyright + and certain other rights specified in the public license below. The + following considerations are for informational purposes only, are not + exhaustive, and do not form part of our licenses. + . + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + . + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More_considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + . + ======================================================================= + . + Creative Commons Attribution 4.0 International Public License + . + By exercising the Licensed Rights (defined below), You accept and agree + to be bound by the terms and conditions of this Creative Commons + Attribution 4.0 International Public License ("Public License"). To the + extent this Public License may be interpreted as a contract, You are + granted the Licensed Rights in consideration of Your acceptance of + these terms and conditions, and the Licensor grants You such rights in + consideration of benefits the Licensor receives from making the + Licensed Material available under these terms and conditions. + . + . + Section 1 -- Definitions. + . + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + . + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + . + c. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + . + d. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + . + e. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + . + f. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + . + g. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + . + h. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + . + i. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + . + j. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + . + k. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + . + . + Section 2 -- Scope. + . + a. License grant. + . + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + . + a. reproduce and Share the Licensed Material, in whole or + in part; and + . + b. produce, reproduce, and Share Adapted Material. + . + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + . + 3. Term. The term of this Public License is specified in Section + 6(a). + . + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + . + 5. Downstream recipients. + . + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + . + b. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + . + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + . + b. Other rights. + . + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + . + 2. Patent and trademark rights are not licensed under this + Public License. + . + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + . + . + Section 3 -- License Conditions. + . + Your exercise of the Licensed Rights is expressly made subject to the + following conditions. + . + a. Attribution. + . + 1. If You Share the Licensed Material (including in modified + form), You must: + . + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + . + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + . + ii. a copyright notice; + . + iii. a notice that refers to this Public License; + . + iv. a notice that refers to the disclaimer of + warranties; + . + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + . + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + . + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + . + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + . + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + . + 4. If You Share Adapted Material You produce, the Adapter's + License You apply must not prevent recipients of the Adapted + Material from complying with this Public License. + . + . + Section 4 -- Sui Generis Database Rights. + . + Where the Licensed Rights include Sui Generis Database Rights that + apply to Your use of the Licensed Material: + . + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + . + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material; and + . + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + . + For the avoidance of doubt, this Section 4 supplements and does not + replace Your obligations under this Public License where the Licensed + Rights include other Copyright and Similar Rights. + . + . + Section 5 -- Disclaimer of Warranties and Limitation of Liability. + . + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + . + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + . + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + . + . + Section 6 -- Term and Termination. + . + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + . + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + . + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + . + 2. upon express reinstatement by the Licensor. + . + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + . + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + . + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + . + . + Section 7 -- Other Terms and Conditions. + . + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + . + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + . + . + Section 8 -- Interpretation. + . + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + . + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + . + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + . + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + . + . + ======================================================================= + . + Creative Commons is not a party to its public licenses. + Notwithstanding, Creative Commons may elect to apply one of its public + licenses to material it publishes and in those instances will be + considered the "Licensor." Except for the limited purpose of indicating + that material is shared under a Creative Commons public license or as + otherwise permitted by the Creative Commons policies published at + creativecommons.org/policies, Creative Commons does not authorize the + use of the trademark "Creative Commons" or any other trademark or logo + of Creative Commons without its prior written consent including, + without limitation, in connection with any unauthorized modifications + to any of its public licenses or any other arrangements, + understandings, or agreements concerning use of licensed material. For + the avoidance of doubt, this paragraph does not form part of the public + licenses. + . + Creative Commons may be contacted at creativecommons.org. + +License: MPL-2.0 + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + . + On Debian systems, see /usr/share/common-licenses/MPL-2.0 for the full + text of the MPL version 2.0. + +License: Zlib + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + . + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + . + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. -- cgit 1.4.1-3-g733a5 From a0c08c68c7db8b8296787fe7ff364a855f0a9295 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 18 Aug 2022 16:03:26 +0200 Subject: cleanup .reuse/dep5 --- .reuse/dep5 | 2145 +---------------------------------------------------------- 1 file changed, 6 insertions(+), 2139 deletions(-) diff --git a/.reuse/dep5 b/.reuse/dep5 index 0afbe833746..e040f73b9e1 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -1,312 +1,9 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: rust -Source: https://www.rust-lang.org Files-Excluded: - *.min.js - src/llvm-emscripten src/llvm-project -# Fonts already in Debian, covered by d-rustdoc-use-system-font.patch -# TODO make that patch, modify src/librustdoc/html/static/css/rustdoc.css - src/librustdoc/html/static/fonts/noto-sans-* -# Pre-generated docs - src/tools/rustfmt/docs -# Proprietary doc formats - src/doc/book/nostarch/docx -# Fonts already in Debian, covered by d-0003-mdbook-strip-embedded-libs.patch - vendor/mdbook/src/theme/fonts - vendor/mdbook/src/theme/FontAwesome - vendor/mdbook/src/theme/highlight.js - vendor/mdbook/src/theme/highlight.css -# Exclude submodules https://github.com/rust-lang/rust/tree/master/src/tools -# We prefer to do them in different Debian packages so they can have their own -# version numbers. If upstream merges them "properly" (i.e. unify the version -# numbers) then we can merge the packages in Debian. Note that cargotest here -# does actually belong to rustc, it is an integration test suite for rustc to -# check that certain popular crates continue to compile. It is not the same as -# cargo's own test suite (in its own package) also called cargotest. -# NB: don't exclude rust-installer, it's needed for "install" functionality - src/tools/cargo - src/tools/rls - src/tools/remote-test-client - src/tools/remote-test-server - src/tools/rust-analyzer - src/tools/miri -# Embedded GH pages - src/tools/clippy/util/gh-pages -# Misc embedded - vendor/structopt/link-check-headers.json -# Embedded C libraries - vendor/libz-sys/src/zlib* - vendor/lzma-sys*/xz-* -# Embedded binary blobs - vendor/jsonpath_lib/docs - vendor/mdbook/src/theme/playground_editor - vendor/psm/src/arch/wasm32.o - vendor/winapi-*/*/*.a -# Embedded submodule used for CI - library/stdarch/crates/intrinsic-test/acle -# NPM packages we can't be bothered documenting licenses for - vendor/tera/docs/node_modules -# unused dependencies, generated by debian/prune-unused-deps -# DO NOT EDIT below, AUTOGENERATED - vendor/addr2line - vendor/adler-0.2.3 - vendor/always-assert - vendor/anymap - vendor/arbitrary - vendor/ar - vendor/arrayvec-0.7.0 - vendor/autocfg-1.0.0 - vendor/backtrace - vendor/bitflags-1.2.1 - vendor/bitmaps - vendor/bytes - vendor/bytesize - vendor/cargo_metadata-0.14.0 - vendor/cc-1.0.69 - vendor/chalk-recursive - vendor/commoncrypto - vendor/commoncrypto-sys - vendor/core-foundation - vendor/core-foundation-sys - vendor/countme - vendor/cov-mark - vendor/cranelift-bforest - vendor/cranelift-codegen - vendor/cranelift-codegen-meta - vendor/cranelift-codegen-shared - vendor/cranelift-entity - vendor/cranelift-frontend - vendor/cranelift-jit - vendor/cranelift-module - vendor/cranelift-native - vendor/cranelift-object - vendor/crc32fast-1.2.0 - vendor/crossbeam-channel-0.5.0 - vendor/crossbeam-utils-0.8.3 - vendor/crypto-hash - vendor/curl - vendor/curl-sys - vendor/dashmap - vendor/derive_arbitrary - vendor/derive_more - vendor/directories - vendor/dot - vendor/drop_bomb - vendor/either-1.6.0 - vendor/enum-iterator - vendor/enum-iterator-derive - vendor/env_logger - vendor/expect-test-1.0.1 - vendor/filetime-0.2.14 - vendor/flate2-1.0.16 - vendor/foreign-types - vendor/foreign-types-shared - vendor/fsevent-sys - vendor/fs_extra-1.1.0 - vendor/fs_extra - vendor/fst-0.4.5 - vendor/fst - vendor/futures-0.1.29 - vendor/futures - vendor/futures-channel - vendor/futures-core - vendor/futures-executor - vendor/futures-io - vendor/futures-macro - vendor/futures-sink - vendor/futures-task - vendor/futures-util - vendor/fwdansi - vendor/getset - vendor/git2 - vendor/git2-curl - vendor/hashbrown-0.11.0 - vendor/heck-0.3.1 - vendor/hex-0.3.2 - vendor/home - vendor/idna-0.1.5 - vendor/idna-0.2.0 - vendor/im-rc - vendor/inotify - vendor/inotify-sys - vendor/itertools-0.10.1 - vendor/itoa-0.4.6 - vendor/jod-thread - vendor/json - vendor/jsonrpc-client-transports - vendor/jsonrpc-core - vendor/jsonrpc-core-client - vendor/jsonrpc-derive - vendor/jsonrpc-ipc-server - vendor/jsonrpc-pubsub - vendor/jsonrpc-server-utils - vendor/kqueue - vendor/kqueue-sys - vendor/lazycell - vendor/libc-0.2.108 - vendor/libgit2-sys - vendor/libloading-0.6.7 - vendor/libloading-0.7.1 - vendor/libmimalloc-sys - vendor/libnghttp2-sys - vendor/libssh2-sys - vendor/libz-sys - vendor/linked-hash-map - vendor/lsp-codec - vendor/lsp-server - vendor/lsp-types-0.60.0 - vendor/lsp-types - vendor/mach - vendor/matches-0.1.8 - vendor/measureme-9.1.2 - vendor/memmap2 - vendor/mimalloc - vendor/miniz_oxide-0.4.0 - vendor/mio-0.7.13 - vendor/mio - vendor/miow - vendor/notify - vendor/ntapi - vendor/object - vendor/once_cell-1.7.2 - vendor/oorandom - vendor/openssl - vendor/openssl-probe - vendor/openssl-src - vendor/openssl-sys - vendor/ordslice - vendor/os_info - vendor/parity-tokio-ipc - vendor/paste - vendor/percent-encoding-1.0.1 - vendor/perf-event - vendor/pin-project-lite-0.2.4 - vendor/pin-utils - vendor/pretty_env_logger - vendor/proc-macro2-1.0.30 - vendor/proc-macro-crate - vendor/proc-macro-hack - vendor/proc-macro-nested - vendor/pulldown-cmark-0.8.0 - vendor/pulldown-cmark-to-cmark - vendor/quote-1.0.7 - vendor/racer - vendor/rand_xoshiro-0.4.0 - vendor/rayon-1.3.1 - vendor/rayon-core-1.7.1 - vendor/regalloc - vendor/region - vendor/rls-vfs - vendor/rowan - vendor/rustc-ap-rustc_arena - vendor/rustc-ap-rustc_ast - vendor/rustc-ap-rustc_ast_pretty - vendor/rustc-ap-rustc_data_structures - vendor/rustc-ap-rustc_errors - vendor/rustc-ap-rustc_feature - vendor/rustc-ap-rustc_fs_util - vendor/rustc-ap-rustc_graphviz - vendor/rustc-ap-rustc_index - vendor/rustc-ap-rustc_lexer-722.0.0 - vendor/rustc-ap-rustc_lexer - vendor/rustc-ap-rustc_lint_defs - vendor/rustc-ap-rustc_macros - vendor/rustc-ap-rustc_parse - vendor/rustc-ap-rustc_serialize - vendor/rustc-ap-rustc_session - vendor/rustc-ap-rustc_span - vendor/rustc-ap-rustc_target - vendor/rustc_version - vendor/ryu-1.0.5 - vendor/salsa - vendor/salsa-macros - vendor/schannel - vendor/security-framework - vendor/security-framework-sys - vendor/semver-1.0.3 - vendor/serde-1.0.125 - vendor/serde_derive-1.0.125 - vendor/serde_ignored - vendor/serde_json-1.0.59 - vendor/serde_repr-0.1.6 - vendor/serde_repr - vendor/sharded-slab-0.1.1 - vendor/signal-hook-registry - vendor/sized-chunks - vendor/slab - vendor/smol_str - vendor/snap-1.0.1 - vendor/socket2 - vendor/strip-ansi-escapes - vendor/syn-1.0.80 - vendor/target-lexicon - vendor/text-size - vendor/thread_local-1.0.1 - vendor/threadpool - vendor/tikv-jemallocator - vendor/tikv-jemalloc-ctl - vendor/tikv-jemalloc-sys-0.4.1+5.2.1-patched - vendor/tikv-jemalloc-sys - vendor/tinyvec-0.3.4 - vendor/tokio - vendor/tokio-stream - vendor/tokio-util - vendor/tower-service - vendor/typed-arena - vendor/ungrammar - vendor/unicode-bidi-0.3.4 - vendor/unicode-normalization-0.1.13 - vendor/unicode-segmentation-1.6.0 - vendor/url-1.7.2 - vendor/utf8parse - vendor/vcpkg - vendor/vergen - vendor/vte - vendor/walkdir-2.3.1 - vendor/windows_aarch64_msvc - vendor/windows_i686_gnu - vendor/windows_i686_msvc - vendor/windows-sys - vendor/windows_x86_64_gnu - vendor/windows_x86_64_msvc - vendor/write-json - vendor/xflags - vendor/xflags-macros - vendor/xshell - vendor/xshell-macros - vendor/yaml-merge-keys - vendor/yaml-rust -# DO NOT EDIT above, AUTOGENERATED -Files: C*.md - R*.md - Cargo.lock - Cargo.toml - COPYRIGHT - LICENSE* - compiler/* - configure - config.toml.example - git-commit-hash - library/* - src/README.md - src/bootstrap/* - src/build_helper/* - src/ci/* - src/doc/* - src/etc/* - src/lib* - src/rust* - src/stage0.json - src/tools/* - src/test/* - src/version - version - x.py -Copyright: 2006-2009 Graydon Hoare - 2009-2012 Mozilla Foundation - 2012-2017 The Rust Project Developers (see AUTHORS.txt) +Files: * +Copyright: The Rust Project Developers (see https://thanks.rust-lang.org) License: MIT or Apache-2.0 Files: library/std/src/sync/mpsc/mpsc_queue.rs @@ -316,1846 +13,16 @@ License: BSD-2-Clause Files: src/librustdoc/html/static/fonts/FiraSans* Copyright: 2014, Mozilla Foundation, 2014, Telefonica S.A. -License: SIL-OPEN-FONT +License: OFL-1.1 Files: src/librustdoc/html/static/fonts/NanumBarun* Copyright: 2010 NAVER Corporation -License: SIL-OPEN-FONT +License: OFL-1.1 Files: src/librustdoc/html/static/fonts/SourceCodePro* Copyright: 2010, 2012 Adobe Systems Incorporated -License: SIL-OPEN-FONT +License: OFL-1.1 Files: src/librustdoc/html/static/fonts/SourceSerif4* Copyright: 2014-2021 Adobe Systems Incorporated -License: SIL-OPEN-FONT - -Files: vendor/compiler_builtins/* -Copyright: 2016-2019 Jorge Aparicio -License: MIT or Apache-2.0 -Comment: see https://github.com/rust-lang-nursery/compiler-builtins - -Files: vendor/compiletest_rs/* -Copyright: 2015-2020 The Rust Project Developers - 2015-2020 Thomas Bracht Laumann Jespersen - 2015-2020 Manish Goregaokar -License: Apache-2.0 or MIT -Comment: see https://github.com/laumann/compiletest-rs - -Files: - vendor/bitflags/* - vendor/cc/* - vendor/cmake/* - vendor/env_logger-0*/* - vendor/getopts/* - vendor/glob/* - vendor/libc/* - vendor/log/* - vendor/regex/* - vendor/regex-syntax/* - vendor/rustc-hash/* - vendor/time/* -Copyright: 2010-2021 The Rust Project Developers -License: MIT or Apache-2.0 -Comment: - This is a collection of external crates embedded here to bootstrap cargo. - Most of them come from the original upstream Rust project, thus share the - same MIT/Apache-2.0 dual-license. See https://github.com/rust-lang. - Exceptions are noted below. - -Files: vendor/num-integer/* - vendor/num-traits/* -Copyright: 2014-2018 The Rust Project Developers -License: MIT or Apache-2.0 -Comment: see https://github.com/rust-num/num - -Files: - vendor/string_cache/* - vendor/string_cache_codegen/* - vendor/unicode-bidi/* -Copyright: 2015-2017 Alex Crichton - 2015-2017 Keegan McAllister - 2015-2017 Chris Morgan - 2014-2017 The html5ever Project Developers - 2014-2017 The Servo Project Developers - 2013-2017 Simon Sapin -License: MIT or Apache-2.0 -Comment: see https://github.com/servo/ - -Files: - vendor/getrandom/* - vendor/getrandom-0*/* - vendor/rand/* - vendor/rand-0*/* - vendor/rand_chacha/* - vendor/rand_chacha-0*/* - vendor/rand_core/* - vendor/rand_core-0*/* - vendor/rand_hc/* - vendor/rand_hc-0*/* - vendor/rand_pcg/* - vendor/rand_xorshift/* - vendor/rand_xoshiro/* -Copyright: 2010-2019 The Rand Project Developers - 2010-2019 The Rust Project Developers -License: MIT or Apache-2.0 -Comment: - see https://github.com/rust-random/getrandom - see https://github.com/rust-random/rand - see https://github.com/rust-random/small-rngs - -Files: - vendor/cfg-if-0*/* - vendor/cfg-if/* - vendor/filetime/* - vendor/flate2/* - vendor/fnv/* - vendor/jobserver/* - vendor/lzma-sys/* - vendor/pkg-config/* - vendor/proc-macro2/* - vendor/rustc-demangle/* - vendor/scoped-tls/* - vendor/tar/* - vendor/toml/* - vendor/xz2/* -Copyright: 2014-2020 Alex Crichton - 2015-2017 The Rust Project Developers -License: MIT or Apache-2.0 -Comment: see https://github.com/alexcrichton/ - -Files: vendor/dlmalloc/* -Copyright: 2017-2019 Alex Crichton -License: MIT or Apache-2.0 -Comment: see https://github.com/alexcrichton/dlmalloc-rs - -Files: vendor/dlmalloc/src/dlmalloc.c -Copyright: 2000-2012 Doug Lea -License: CC0-1.0 - -Files: vendor/tester/* -Copyright: 2016-2019 The Rust Project Developers -License: MIT OR Apache-2.0 -Comment: see https://github.com/messense/rustc-test - -Files: vendor/addr2line-0*/* -Copyright: - 2016-2021 Nick Fitzgerald - 2016-2021 Philip Craig - 2016-2021 Jon Gjengset - 2016-2021 Noah Bergbauer -License: Apache-2.0 or MIT -Comment: see https://github.com/gimli-rs/addr2line - -Files: vendor/adler/* -Copyright: 2020-2020 Jonas Schievink -License: 0BSD or MIT or Apache-2.0 -Comment: see https://github.com/jonas-schievink/adler.git - -Files: vendor/ammonia/* -Copyright: 2015-2018 Michael Howell -License: MIT or Apache-2.0 -Comment: see https://github.com/notriddle/ammonia - -Files: vendor/annotate-snippets/* -Copyright: 2018-2020 Zibi Braniecki -License: Apache-2.0 or MIT -Comment: see https://github.com/zbraniecki/annotate-snippets-rs - -Files: - vendor/ansi_term/* - vendor/ansi_term-0*/* -Copyright: - 2014-2020 ogham@bsago.me - 2014-2020 Ryan Scheel (Havvy) - 2014-2020 Josh Triplett -License: MIT -Comment: see https://github.com/ogham/rust-ansi-term - -Files: vendor/aho-corasick/* - vendor/memchr/* -Copyright: 2015 Andrew Gallant - 2015-2018 bluss -License: MIT or Unlicense -Comment: see upstream projects, - * https://github.com/BurntSushi/aho-corasick - * https://github.com/BurntSushi/rust-memchr - -Files: vendor/array_tool/* -Copyright: 2015-2018 Daniel P. Clark <6ftdan@gmail.com> -License: MIT OR Apache-2.0 -Comment: see https://github.com/danielpclark/array_tool - -Files: vendor/autocfg/* -Copyright: 2018-2020 Josh Stone -License: Apache-2.0 or MIT - -Files: vendor/atty/* -Copyright: 2015-2017 softprops -License: MIT -Comment: see https://github.com/softprops/atty - -Files: - vendor/block-buffer/* - vendor/block-buffer-0*/* - vendor/block-padding/* - vendor/byte-tools/* - vendor/cpuid-bool/* - vendor/digest/* - vendor/digest-0*/* - vendor/fake-simd/* - vendor/md-5/* - vendor/opaque-debug/* - vendor/opaque-debug-0*/* - vendor/sha-1-0*/* - vendor/sha-1/* - vendor/sha2/* -Copyright: 2016-2020 RustCrypto Developers -License: MIT or Apache-2.0 -Comment: - see https://github.com/RustCrypto/hashes - see https://github.com/RustCrypto/traits - see https://github.com/RustCrypto/utils - -Files: vendor/bstr/* -Copyright: 2018-2020 Andrew Gallant -License: MIT OR Apache-2.0 -Comment: see https://github.com/BurntSushi/bstr - -Files: vendor/bytecount/* -Copyright: 2016-2020 Andre Bogus - 2016-2020 Joshua Landau -License: Apache-2.0 or MIT -Comment: see https://github.com/llogiq/bytecount - -Files: - vendor/byteorder/* - vendor/globset/* - vendor/ignore/* - vendor/same-file/* - vendor/termcolor/* - vendor/walkdir/* - vendor/winapi-util/* -Copyright: 2015-2020 Andrew Gallant -License: Unlicense or MIT -Comment: - see https://github.com/BurntSushi/byteorder - see https://github.com/BurntSushi/same-file - see https://github.com/BurntSushi/walkdir - see https://github.com/BurntSushi/winapi-util - see https://github.com/BurntSushi/ripgrep/tree/master/globset - see https://github.com/BurntSushi/ripgrep/tree/master/ignore - see https://github.com/BurntSushi/ripgrep/tree/master/termcolor - -Files: vendor/camino/* -Copyright: 2020-2022 Without Boats - 2020-2022 Ashley Williams - 2020-2022 Steve Klabnik - 2020-2022 Rain -License: MIT OR Apache-2.0 -Comment: see https://github.com/withoutboats/camino - -Files: - vendor/cargo_metadata/* - vendor/cargo_metadata-0*/* -Copyright: 2016-2020 Oliver Schneider -License: MIT -Comment: - see https://github.com/oli-obk/cargo_metadata - -Files: vendor/cargo-platform/* -Copyright: 2019-2022 The Cargo Project Developers -License: MIT OR Apache-2.0 -Comment: see https://github.com/rust-lang/cargo - -Files: vendor/ppv-lite86/* -Copyright: 2019-2019 The CryptoCorrosion Contributors -License: MIT or Apache-2.0 -Comment: see https://github.com/cryptocorrosion/cryptocorrosion - -Files: - vendor/chalk-derive/* - vendor/chalk-engine/* - vendor/chalk-ir/* - vendor/chalk-solve/* -Copyright: - 2015-2022 Rust Compiler Team - 2015-2022 Chalk developers -License: Apache-2.0 or MIT -Comment: see https://github.com/rust-lang/chalk - -Files: vendor/chrono/* -Copyright: 2014-2018 Kang Seonghoon -License: MIT or Apache-2.0 -Comment: see https://github.com/chronotope/chrono - -Files: vendor/clap/* -Copyright: 2015-2017 Kevin K. -License: MIT -Comment: see https://github.com/kbknapp/clap-rs.git - -Files: vendor/colored/* -Copyright: 2016-2020 Thomas Wickham -License: MPL-2.0 -Comment: see https://github.com/mackwic/colored - -Files: vendor/crc32fast/* -Copyright: 2018-2019 Sam Rijs - 2018-2019 Alex Crichton -License: MIT OR Apache-2.0 -Comment: see https://github.com/srijs/rust-crc32fast - -Files: - vendor/crossbeam-channel/* - vendor/crossbeam-deque/* - vendor/crossbeam-deque-0*/* - vendor/crossbeam-epoch/* - vendor/crossbeam-epoch-0*/* - vendor/crossbeam-queue/* - vendor/crossbeam-utils/* - vendor/crossbeam-utils-0*/* -Copyright: 2015-2021 The Crossbeam Project Developers -License: MIT or Apache-2.0 -Comment: see https://github.com/crossbeam-rs - -Files: vendor/cstr/* -Copyright: 2018-2020 Xidorn Quan -License: MIT -Comment: see https://github.com/upsuper/cstr - -Files: vendor/ctor/* -Copyright: 2018-2020 Matt Mastracci -License: Apache-2.0 OR MIT -Comment: see https://github.com/mmastrac/rust-ctor - -Files: vendor/datafrog/* -Copyright: - 2018 Frank McSherry - 2018 The Rust Project Developers - 2018 Datafrog Developers -License: Apache-2.0 or MIT -Comment: see https://github.com/rust-lang-nursery/datafrog - -Files: vendor/derive-new/* -Copyright: 2016-2020 Nick Cameron -License: MIT -Comment: see https://github.com/nrc/derive-new - -Files: vendor/diff/* -Copyright: 2015-2017 Utkarsh Kukreti -License: MIT or Apache-2.0 -Comment: see https://github.com/utkarshkukreti/diff.rs - -Files: - vendor/anyhow/* - vendor/dissimilar/* - vendor/itoa/* - vendor/quote/* - vendor/syn/* -Copyright: 2016-2022 David Tolnay -License: MIT or Apache-2.0 -Comment: - see https://github.com/dtolnay/anyhow - see https://github.com/dtolnay/dissimilar - see https://github.com/dtolnay/itoa - see https://github.com/dtolnay/quote - see https://github.com/dtolnay/syn - -Files: - vendor/arrayvec/* - vendor/either/* - vendor/fixedbitset/* - vendor/itertools/* - vendor/itertools-0*/* - vendor/maplit/* - vendor/scopeguard/* -Copyright: 2014-2020 bluss -License: MIT or Apache-2.0 -Comment: - see https://github.com/bluss/rust-itertools - see https://github.com/bluss/either - see https://github.com/bluss/arrayvec - see https://github.com/bluss/fixedbitset - see https://github.com/bluss/maplit - see https://github.com/bluss/scopeguard - -Files: vendor/difference/* -Copyright: 2015-2018 Johann Hofmann -License: MIT -Comment: see https://github.com/johannhof/difference.rs - -Files: - vendor/dirs/* - vendor/dirs-sys/* -Copyright: 2015-2020 Simon Ochsenreither - 2015-2020 dirs-rs contributors -License: MIT OR Apache-2.0 -Comment: - see https://github.com/dirs-dev/dirs-rs - see https://github.com/dirs-dev/dirs-sys-rs - -Files: - vendor/dirs-next/* - vendor/dirs-sys-next/* -Copyright: 2017-2021 The @xdg-rs members -License: MIT OR Apache-2.0 -Comment: see https://github.com/xdg-rs/dirs - -Files: vendor/elasticlunr-rs/* -Copyright: 2017-2018 Matt Ickstadt -License: MIT or Apache-2.0 -Comment: see https://github.com/mattico/elasticlunr-rs - -Files: vendor/ena/* -Copyright: 2015-2020 Niko Matsakis -License: MIT or Apache-2.0 -Comment: see https://github.com/nikomatsakis/ena - -Files: vendor/expect-test/* -Copyright: 2020-2022 rust-analyzer developers -License: MIT OR Apache-2.0 -Comment: see https://github.com/rust-analyzer/expect-test - -Files: vendor/fallible-iterator/* -Copyright: 2016-2019 Steven Fackler -License: MIT or Apache-2.0 -Comment: see https://github.com/sfackler/rust-fallible-iterator - -Files: vendor/fortanix-sgx-abi/* -Copyright: 2015-2019 Jethro Beekman -License: MPL-2.0 -Comment: see https://github.com/fortanix/rust-sgx - -Files: vendor/fs-err/* -Copyright: 2020-2020 Andrew Hickman -License: MIT or Apache-2.0 -Comment: see https://github.com/andrewhickman/fs-err - -Files: vendor/futf/* -Copyright: 2015-2018 Keegan McAllister -License: MIT or Apache-2.0 -Comment: see https://github.com/servo/futf - -Files: - vendor/generic-array/* - vendor/generic-array-0*/* -Copyright: - 2015-2020 Bartłomiej Kamiński - 2015-2020 Aaron Trent -License: MIT -Comment: see https://github.com/fizyk20/generic-array.git - -Files: - vendor/gimli-0*/* - vendor/gimli/* -Copyright: - 2016-2021 Nick Fitzgerald - 2016-2021 Philip Craig -License: Apache-2.0 or MIT -Comment: see https://github.com/gimli-rs/gimli - -Files: vendor/globwalk/* -Copyright: 2018-2020 Gilad Naaman -License: MIT -Comment: see https://github.com/gilnaa/globwalk - -Files: vendor/gsgdt/* -Copyright: 2020 Vishnunarayan K I -License: MIT or Apache-2.0 -Comment: see https://github.com/vn-ki/gsgdt-rs - -Files: vendor/handlebars/* -Copyright: 2014-2017 Ning Sun -License: MIT -Comment: see https://github.com/sunng87/handlebars-rust - -Files: vendor/heck/* -Copyright: 2017-2018 Without Boats -License: MIT OR Apache-2.0 -Comment: see https://github.com/withoutboats/heck - -Files: vendor/hermit-abi/* -Copyright: 2019-2019 Stefan Lankes -License: MIT or Apache-2.0 -Comment: see https://github.com/hermitcore/hermit-abi - -Files: vendor/hex/* -Copyright: 2015-2020 KokaKiwi -License: MIT OR Apache-2.0 -Comment: see https://github.com/KokaKiwi/rust-hex - -Files: - vendor/html5ever/* - vendor/markup5ever/* - vendor/markup5ever_rcdom/* -Copyright: 2014-2020 The html5ever Project Developers -License: MIT or Apache-2.0 -Comment: see https://github.com/servo/html5ever - -Files: - vendor/humantime/* - vendor/humantime-*/* -Copyright: - 2016-2018 Paul Colomiets - 2016 The humantime Developers - 2016 Pyfisch - 2005-2013 Rich Felker -License: MIT or Apache-2.0 - -Files: vendor/if_chain/* -Copyright: 2016-2020 Chris Wong -License: MIT or Apache-2.0 -Comment: see https://github.com/lfairy/if_chain - -Files: - vendor/form_urlencoded/* - vendor/idna/* - vendor/percent-encoding/* - vendor/url/* -Copyright: 2013-2021 The rust-url developers -License: MIT or Apache-2.0 -Comment: see https://github.com/servo/rust-url/ - -Files: vendor/indexmap/* -Copyright: 2016-2019 bluss - 2016-2019 Josh Stone -License: Apache-2.0 or MIT -Comment: see https://github.com/bluss/indexmap - -Files: - vendor/indoc/* - vendor/unindent/* -Copyright: 2016-2022 David Tolnay -License: MIT OR Apache-2.0 -Comment: see https://github.com/dtolnay/indoc - -Files: vendor/instant/* -Copyright: 2019-2020 sebcrozet -License: BSD-3-Clause -Comment: see https://github.com/sebcrozet/instant - -Files: vendor/jsonpath_lib/* -Copyright: 2018-2021 Changseok Han -License: MIT -Comment: see https://github.com/freestrings/jsonpath - -Files: vendor/lazy_static/* -Copyright: 2014-2018 Marvin Löbel -License: MIT or Apache-2.0 -Comment: - see https://github.com/rust-lang-nursery/lazy-static.rs - see https://github.com/Kimundi/owning-ref-rs - -Files: vendor/libloading/* -Copyright: 2015-2022 Simonas Kazlauskas -License: ISC -Comment: see https://github.com/nagisa/rust_libloading/ - -Files: vendor/libm/* -Copyright: 2018-2021 Jorge Aparicio -License: MIT OR Apache-2.0 -Comment: see https://github.com/rust-lang-nursery/libm - -Files: vendor/mac/* -Copyright: 2014-2017 Jonathan Reem -License: MIT -Comment: - see https://github.com/reem/rust-mac.git - -Files: vendor/matchers/* -Copyright: 2019-2019 Eliza Weisman -License: MIT -Comment: see https://github.com/hawkw/matchers - -Files: vendor/matches/* -Copyright: 2014-2017 Simon Sapin -License: MIT -Comment: see https://github.com/SimonSapin - -Files: vendor/maybe-uninit/* -Copyright: 2019-2019 est31 - 2019-2019 The Rust Project Developers -License: Apache-2.0 OR MIT -Comment: see https://github.com/est31/maybe-uninit - -Files: vendor/mdbook/* -Copyright: 2015-2017 Mathieu David -License: MPL-2.0 -Comment: see https://github.com/azerupi/mdBook - -Files: vendor/measureme/* -Copyright: 2019-2020 Wesley Wiser - 2019-2020 Michael Woerister -License: MIT OR Apache-2.0 -Comment: see https://github.com/rust-lang/measureme - -Files: vendor/memmap2-0*/* -Copyright: 2015-2021 Dan Burkert - 2015-2021 Evgeniy Reizner -License: MIT or Apache-2.0 -Comment: see https://github.com/RazrFalcon/memmap2-rs - -Files: - vendor/memoffset/* - vendor/memoffset-0*/* -Copyright: 2017-2019 Gilad Naaman -License: MIT -Comment: see https://github.com/Gilnaa/memoffset - -Files: - vendor/macro-utils/* - vendor/minifier/* -Copyright: 2017-2018 Guillaume Gomez -License: MIT -Comment: - see https://github.com/GuillaumeGomez/macro_utils - see https://github.com/GuillaumeGomez/minifier-rs - -Files: - vendor/miniz_oxide/* -Copyright: 2017-2020 Frommi -License: MIT -Comment: see https://github.com/Frommi/miniz_oxide - -Files: vendor/miow-0.3.7/* -Copyright: 2014-2021 Alex Crichton -License: MIT or Apache-2.0 -Comment: see https://github.com/yoshuawuyts/miow - -Files: vendor/new_debug_unreachable/* -Copyright: 2014-2018 Matt Brubeck - 2014-2018 Jonathan Reem -License: MIT -Comment: see https://github.com/mbrubeck/rust-debug-unreachable - -Files: vendor/num_cpus/* -Copyright: 2015 Sean McArthur -License: MIT -Comment: see https://github.com/seanmonstar/num_cpus - -Files: vendor/object-0*/* -Copyright: - 2016-2020 Nick Fitzgerald - 2016-2020 Philip Craig -License: Apache-2.0 or MIT -Comment: see https://github.com/gimli-rs/object - -Files: vendor/odht/* -Copyright: 2021 Michael Woerister -License: Apache-2.0 or MIT -Comment: see https://github.com/rust-lang/odht - -Files: vendor/opener/* -Copyright: 2018-2020 Brian Bowman -License: MIT OR Apache-2.0 -Comment: see https://github.com/Seeker14491/opener - -Files: vendor/once_cell/* -Copyright: 2018-2019 Aleksey Kladov -License: MIT OR Apache-2.0 -Comment: see https://github.com/matklad/once_cell - -Files: vendor/output_vt100/* -Copyright: 2019-2019 Phuntsok Drak-pa -License: MIT -Comment: see https://github.com/Phundrak/output-vt100-rs - -Files: - vendor/hashbrown/* - vendor/lock_api/* - vendor/thread_local/* - vendor/parking_lot/* - vendor/parking_lot_core/* -Copyright: 2016-2019 Amanieu d'Antras -License: MIT or Apache-2.0 -Comment: - see https://github.com/rust-lang/hashbrown - see https://github.com/Amanieu/thread_local-rs - see https://github.com/Amanieu/parking_lot - -Files: vendor/packed_simd_2/* -Copyright: 2018-2021 Gonzalo Brito Gadeschi - 2018-2021 Jubilee Young -License: MIT or Apache-2.0 -Comment: see https://github.com/rust-lang-nursery/packed_simd - -Files: vendor/pathdiff/* -Copyright: 2017-2020 Manish Goregaokar -License: MIT or Apache-2.0 -Comment: see https://github.com/Manishearth/pathdiff - -Files: vendor/perf-event-open-sys/* -Copyright: 2019-2020 Jim Blandy -License: MIT OR Apache-2.0 -Comment: see https://github.com/jimblandy/perf-event.git - -Files: - vendor/pest/* - vendor/pest_derive/* - vendor/pest_generator/* - vendor/pest_meta/* -Copyright: 2016-2019 Dragoș Tiselice -License: MIT or Apache-2.0 -Comment: - see https://github.com/dragostis/pest - see https://github.com/pest-parser/pest - -Files: vendor/polonius-engine/* -Copyright: 2018-2018 The Rust Project Developers - 2018-2018 Polonius Developers -License: Apache-2.0 or MIT -Comment: see https://github.com/rust-lang-nursery/polonius - -Files: vendor/petgraph/* -Copyright: 2014-2018 bluss - 2014-2018 mitchmindtree -License: MIT or Apache-2.0 -Comment: see https://github.com/bluss/petgraph - -Files: - vendor/phf/* - vendor/phf_codegen/* - vendor/phf_generator/* - vendor/phf_shared/* -Copyright: 2014-2018 Steven Fackler -License: MIT -Comment: see https://github.com/sfackler/rust-phf - -Files: vendor/pin-project-lite/* -Copyright: 2018-2021 Taiki Endo -License: Apache-2.0 or MIT -Comment: - see https://github.com/taiki-e/pin-project-lite - -Files: vendor/precomputed-hash/* -Copyright: 2017-2017 Emilio Cobos Álvarez -License: MIT -Comment: see https://github.com/emilio/precomputed-hash - -Files: vendor/pretty_assertions/* -Copyright: 2017-2018 Colin Kiegel - 2017-2018 Florent Fayolle -License: MIT or Apache-2.0 -Comment: see https://github.com/colin-kiegel/rust-pretty-assertions - -Files: - vendor/proc-macro-error/* - vendor/proc-macro-error-attr/* -Copyright: 2019-2020 CreepySkeleton -License: MIT OR Apache-2.0 -Comment: see https://gitlab.com/CreepySkeleton/proc-macro-error - -Files: vendor/psm/* -Copyright: 2015-2020 Simonas Kazlauskas -License: MIT or Apache-2.0 -Comment: see https://github.com/rust-lang/stacker/ - -Files: vendor/pulldown-cmark/* -Copyright: 2015-2017 Raph Levien -License: MIT -Comment: see https://github.com/google/pulldown-cmark - -Files: vendor/punycode/* -Copyright: 2015-2019 mcarton -License: MIT -Comment: see https://github.com/mcarton/rust-punycode.git - -Files: - vendor/quick-error/* - vendor/quick-error-1*/* -Copyright: - 2015-2020 Paul Colomiets - 2015-2020 Colin Kiegel -License: MIT or Apache-2.0 -Comment: see http://github.com/tailhook/quick-error - -Files: vendor/quine-mc_cluskey/* -Copyright: 2016-2016 Oliver Schneider -License: MIT -Comment: see https://github.com/oli-obk/quine-mc_cluskey - -Files: - vendor/rayon/* - vendor/rayon-core/* - vendor/rustc-rayon/* - vendor/rustc-rayon-core/* -Copyright: 2014-2018 Niko Matsakis - 2014-2018 Josh Stone -License: Apache-2.0 or MIT -Comment: - see https://github.com/rayon-rs/rayon - see https://github.com/Zoxc/rayon/tree/rustc - -Files: vendor/redox_users/* -Copyright: 2017-2021 Jose Narvaez - 2017-2021 Wesley Hershberger -License: MIT -Comment: see https://gitlab.redox-os.org/redox-os/users - -Files: vendor/redox_syscall/* -Copyright: 2016-2021 Jeremy Soller -License: MIT -Comment: - see https://github.com/redox-os/syscall - -Files: vendor/regex-automata/* -Copyright: 2018-2020 Andrew Gallant -License: Unlicense or MIT -Comment: see https://github.com/BurntSushi/regex-automata - -Files: vendor/remove_dir_all/* -Copyright: 2017-2018 Aaronepower -License: MIT or Apache-2.0 -Comment: see https://github.com/Aaronepower/remove_dir_all.git - -Files: vendor/rls-data/* - vendor/rls-span/* -Copyright: 2016-2017 Nick Cameron -License: Apache-2.0 or MIT -Comment: see https://github.com/nrc/rls-span - see https://github.com/nrc/rls-data - -Files: vendor/rustc-semver/* -Copyright: 2020-2020 flip1995 -License: MIT OR Apache-2.0 -Comment: see https://github.com/flip1995/rustc-semver - -Files: vendor/rustc_tools_util/* -Copyright: 2014-2021 Matthias Krüger -License: MIT or Apache-2.0 -Comment: see https://github.com/rust-lang/rust-clippy - -Files: - vendor/rustfix/* - vendor/rustfix-0*/* -Copyright: - 2016-2021 Pascal Hertleif - 2016-2021 Oliver Schneider -License: Apache-2.0 or MIT -Comment: see https://github.com/killercup/rustfix - -Files: vendor/rustversion/* -Copyright: 2019-2021 David Tolnay -License: MIT OR Apache-2.0 -Comment: see https://github.com/dtolnay/rustversion - -Files: vendor/ryu/* -Copyright: 2018-2018 David Tolnay -License: Apache-2.0 or BSL-1.0 -Comment: see https://github.com/dtolnay/ryu - -Files: - vendor/semver-0*/* - vendor/semver/* - vendor/semver-parser/* -Copyright: - 2014-2020 Steve Klabnik - 2014-2020 The Rust Project Developers -License: MIT or Apache-2.0 -Comment: - see https://github.com/steveklabnik/semver - see https://github.com/steveklabnik/semver-parser - -Files: vendor/serde/* - vendor/serde_json/* -Copyright: 2014-2017 Erick Tryzelaar -License: MIT or Apache-2.0 -Comment: - see https://github.com/serde-rs/serde - see https://github.com/serde-rs/json - -Files: vendor/serde_derive/* -Copyright: 2014-2017 Erick Tryzelaar - 2016-2017 David Tolnay -License: MIT or Apache-2.0 -Comment: see https://github.com/serde-rs/serde - -Files: vendor/sharded-slab/* -Copyright: 2019-2020 Eliza Weisman -License: MIT -Comment: see https://github.com/hawkw/sharded-slab - -Files: vendor/shell-escape/* -Copyright: 2016-2020 Steven Fackler -License: MIT or Apache-2.0 -Comment: see https://github.com/sfackler/shell-escape - -Files: vendor/shlex/* -Copyright: 2015-2015 comex -License: MIT or Apache-2.0 -Comment: see https://github.com/comex/rust-shlex - -Files: vendor/siphasher/* -Copyright: 2016-2018 Frank Denis -License: MIT or Apache-2.0 -Comment: see https://github.com/jedisct1/rust-siphash - -Files: vendor/smallvec/* -Copyright: 2015-2020 Simon Sapin -License: MPL-2.0 -Comment: see https://github.com/servo/rust-smallvec - -Files: vendor/snap/* -Copyright: 2016-2020 Andrew Gallant -License: BSD-3-Clause -Comment: see https://github.com/BurntSushi/rust-snappy - -Files: vendor/stable_deref_trait/* -Copyright: 2017-2017 Robert Grosse -License: MIT or Apache-2.0 -Comment: see https://github.com/storyyeller/stable_deref_trait - -Files: vendor/stacker/* -Copyright: 2015-2020 Alex Crichton - 2015-2020 Simonas Kazlauskas -License: MIT or Apache-2.0 -Comment: see https://github.com/rust-lang/stacker - -Files: vendor/strsim/* -Copyright: 2015 Danny Guo -License: MIT -Comment: see https://github.com/dguo/strsim-rs - -Files: - vendor/structopt/* - vendor/structopt-derive/* -Copyright: 2017-2020 Guillaume Pinot - 2017-2020 others -License: Apache-2.0 OR MIT -Comment: see https://github.com/TeXitoi/structopt - -Files: - vendor/strum/* - vendor/strum_macros/* -Copyright: 2015-2018 Peter Glotfelty -License: MIT - -Files: vendor/synstructure/* -Copyright: - 2016-2019 Nika Layzell -License: MIT -Comment: see https://github.com/mystor/synstructure - -Files: vendor/tempfile/* -Copyright: 2015-2018 Steven Allen - 2015-2018 The Rust Project Developers - 2015-2018 Ashley Mannix - 2015-2018 Jason White -License: MIT or Apache-2.0 -Comment: see https://github.com/Stebalien/tempfile - -Files: vendor/tendril/* -Copyright: 2015-2017 Keegan McAllister - 2015-2017 Simon Sapin - 2015-2017 Chris Morgan -License: MIT or Apache-2.0 -Comment: see https://github.com/servo/tendril - -Files: vendor/tera/* -Copyright: 2015-2021 Vincent Prouillet -License: MIT -Comment: see https://github.com/Keats/tera - -Files: - vendor/term/* - vendor/term-0*/* -Copyright: - 2014-2021 The Rust Project Developers - 2014-2021 Steven Allen -License: MIT or Apache-2.0 -Comment: see https://github.com/Stebalien/term - -Files: vendor/termize/* -Copyright: 2016-2020 Yuki Okushi -License: MIT or Apache-2.0 -Comment: see https://github.com/JohnTitor/termize - -Files: vendor/textwrap/* -Copyright: 2016-2017 Martin Geisler -License: MIT -Comment: see https://github.com/mgeisler/textwrap - -Files: - vendor/thiserror/* - vendor/thiserror-impl/* -Copyright: 2019-2020 David Tolnay -License: MIT OR Apache-2.0 -Comment: see https://github.com/dtolnay/thiserror - -Files: vendor/thorin-dwp/* -Copyright: 2021-2022 David Wood -License: MIT OR Apache-2.0 -Comment: see https://github.com/davidtwco/thorin - -Files: vendor/tinyvec/* -Copyright: 2020 Lokathor -License: Zlib -Comment: see https://github.com/Lokathor/tinyvec - -Files: vendor/tinyvec_macros/* -Copyright: 2020 Soveu -License: MIT or Apache-2.0 or Zlib -Comment: see https://github.com/Soveu/tinyvec_macros - -Files: vendor/topological-sort/* -Copyright: 2015-2018 gifnksm -License: MIT OR Apache-2.0 -Comment: see https://github.com/gifnksm/topological-sort-rs - -Files: - vendor/tracing/* - vendor/tracing-attributes/* - vendor/tracing-core/* - vendor/tracing-log/* - vendor/tracing-subscriber/* -Copyright: - 2018-2020 Eliza Weisman - 2018-2020 Tokio Contributors - 2018-2020 David Barsky -License: MIT -Comment: see https://github.com/tokio-rs/tracing - -Files: vendor/tracing-tree/* -Copyright: 2020-2020 David Barsky - 2020-2020 Nathan Whitaker -License: MIT OR Apache-2.0 -Comment: see https://github.com/davidbarsky/tracing-tree - -Files: vendor/typenum/* -Copyright: 2015-2019 Paho Lurie-Gregg - 2015-2019 Andre Bogus -License: MIT or Apache-2.0 -Comment: see https://github.com/paholg/typenum - -Files: vendor/version_check/* -Copyright: 2017-2019 Sergio Benitez -License: MIT or Apache-2.0 -Comment: see https://github.com/SergioBenitez/version_check - -Files: - vendor/ucd-parse/* - vendor/ucd-trie/* -Copyright: 2017-2020 Andrew Gallant -License: MIT or Apache-2.0 -Comment: - see https://github.com/BurntSushi/rucd - see https://github.com/BurntSushi/ucd-generate - -Files: vendor/unicase/* -Copyright: 2014-2019 Sean McArthur -License: MIT or Apache-2.0 -Comment: see https://github.com/seanmonstar/unicase - -Files: vendor/unicode_categories/* -Copyright: 2015-2016 Sean Gillespie -License: MIT OR Apache-2.0 -Comment: see https://github.com/swgillespie/unicode-categories - -Files: vendor/unic-*/* -Copyright: 2017-2022 The UNIC Project Developers -License: MIT or Apache-2.0 -Comment: see https://github.com/open-i18n/rust-unic/ - -Files: - vendor/unicode-normalization/* - vendor/unicode-segmentation/* - vendor/unicode-width/* -Copyright: 2015-2019 kwantam -License: MIT or Apache-2.0 -Comment: - see https://github.com/unicode-rs/unicode-normalization - see https://github.com/unicode-rs/unicode-segmentation - see https://github.com/unicode-rs/unicode-width - -Files: vendor/unicode-xid/* -Copyright: 2015-2017 erick.tryzelaar - 2015-2017 kwantam -License: MIT or Apache-2.0 -Comment: see https://github.com/unicode-rs/unicode-xid - -Files: vendor/unicode-script/* -Copyright: 2017-2020 Manish Goregaokar -License: MIT or Apache-2.0 -Comment: see https://github.com/unicode-rs/unicode-script - -Files: vendor/unicode-security/* -Copyright: 2020-2020 Charles Lew - 2020-2020 Manish Goregaokar -License: MIT or Apache-2.0 -Comment: see https://github.com/unicode-rs/unicode-security - -Files: vendor/unified-diff/* -Copyright: 2021-2021 Michael Howell - 2021-2021 The Rust Project Developers -License: MIT OR Apache-2.0 -Comment: see https://github.com/notriddle/rust-unified-diff - -Files: vendor/utf-8/* -Copyright: 2015-2018 Simon Sapin -License: MIT OR Apache-2.0 -Comment: see https://github.com/SimonSapin/rust-utf8 - -Files: vendor/vec_map/* -Copyright: 2015-2017 Alexis Beingessner - 2015-2017 Andrew Paseltiner - 2015-2017 contain-rs developers - 2015-2017 The Rust Project Developers -License: MIT or Apache-2.0 -Comment: see https://github.com/contain-rs/vec-map - -Files: vendor/wasi/* -Copyright: 2019-2020 The Cranelift Project Developers -License: Apache-2.0 with LLVM exception or Apache-2.0 or MIT -Comment: see https://github.com/CraneStation/rust-wasi - -Files: vendor/winapi/* -Copyright: - 2014-2019 Peter Atashian - 2014-2019 winapi-rs developers -License: MIT -Comment: see https://github.com/retep998/winapi-rs - -Files: vendor/winapi-*-pc-windows-gnu/* -Copyright: 2014-2018 Peter Atashian -License: MIT or Apache-2.0 -Comment: see https://github.com/retep998/winapi-rs - -Files: vendor/xattr/* -Copyright: 2015-2017 Steven Allen -License: MIT or Apache-2.0 -Comment: see https://github.com/Stebalien/xattr - -Files: vendor/xml5ever/* -Copyright: 2014-2020 The xml5ever project developers -License: MIT or Apache-2.0 -Comment: see https://github.com/servo/html5ever - -Files: vendor/yaml-rust-0*/* -Copyright: 2015-2020 Yuheng Chen -License: MIT or Apache-2.0 -Comment: see https://github.com/chyh1990/yaml-rust - -Files: vendor/yansi-term/* -Copyright: 2014-2020 ogham@bsago.me - 2014-2020 Ryan Scheel (Havvy) - 2014-2020 Josh Triplett - 2014-2020 Juan Aguilar Santillana -License: MIT -Comment: see https://github.com/botika/yansi-term - -Files: debian/* -Copyright: 2013-2018 Debian Rust Maintainers -License: MIT or Apache-2.0 - -Files: debian/icons/rust-logo-32x32-blk.png -Copyright: Mozilla Foundation -License: CC-BY -Comment: - Relevant discussion in https://github.com/rust-lang/rust/issues/11562 - -License: 0BSD - Permission to use, copy, modify, and/or distribute this software for - any purpose with or without fee is hereby granted. - . - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -License: Apache-2.0 - On Debian systems, the full text of the Apache License Version 2.0 - can be found in the file `/usr/share/common-licenses/Apache-2.0'. - -License: Apache-2.0 with LLVM exception - On Debian systems, the full text of the Apache License Version 2.0 - can be found in the file `/usr/share/common-licenses/Apache-2.0'. - Additionally, the LLVM exception is as follows: - . - As an exception, if, as a result of your compiling your source code, portions - of this Software are embedded into an Object form of such source code, you - may redistribute such embedded portions in such Object form without complying - with the conditions of Sections 4(a), 4(b) and 4(d) of the License. - . - In addition, if you combine or link compiled forms of this Software with - software that is licensed under the GPLv2 ("Combined Software") and if a - court of competent jurisdiction determines that the patent provision (Section - 3), the indemnity provision (Section 9) or other Section of the License - conflicts with the conditions of the GPLv2, you may retroactively and - prospectively choose to deem waived or otherwise exclude such Section(s) of - the License, but only in their entirety and only with respect to the Combined - Software. - -License: BSD-2-clause - Redistribution and use in source and binary forms, with - or without modification, are permitted provided that the - following conditions are met: - . - 1. Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - 2. Redistributions in binary form must reproduce the - above copyright notice, this list of conditions and - the following disclaimer in the documentation and/or - other materials provided with the distribution. - . - THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -License: CC0-1.0 - On Debian systems, the full text of the CC0 1.0 Universal - License can be found in the file - `/usr/share/common-licenses/CC0-1.0'. - -License: ISC - Permission to use, copy, modify, and/or distribute this software for any purpose - with or without fee is hereby granted, provided that the above copyright notice - and this permission notice appear in all copies. - . - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF - THIS SOFTWARE. - -License: MIT - Permission is hereby granted, free of charge, to any - person obtaining a copy of this software and associated - documentation files (the "Software"), to deal in the - Software without restriction, including without - limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of - the Software, and to permit persons to whom the Software - is furnished to do so, subject to the following - conditions: - . - The above copyright notice and this permission notice - shall be included in all copies or substantial portions - of the Software. - . - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF - ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED - TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT - SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR - IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - -License: BSL-1.0 - Permission is hereby granted, free of charge, to any person or organization - obtaining a copy of the software and accompanying documentation covered by - this license (the "Software") to use, reproduce, display, distribute, - execute, and transmit the Software, and to prepare derivative works of the - Software, and to permit third-parties to whom the Software is furnished to - do so, all subject to the following: - . - The copyright notices in the Software and this entire statement, including - the above license grant, this restriction and the following disclaimer, - must be included in all copies of the Software, in whole or in part, and - all derivative works of the Software, unless such copies or derivative - works are solely in the form of machine-executable object code generated by - a source language processor. - . - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT - SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE - FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - -License: BSD-3-clause - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the organization nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - . - THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - -License: Unlicense - This is free and unencumbered software released into the public domain. - . - Anyone is free to copy, modify, publish, use, compile, sell, or - distribute this software, either in source code form or as a compiled - binary, for any purpose, commercial or non-commercial, and by any - means. - . - In jurisdictions that recognize copyright laws, the author or authors - of this software dedicate any and all copyright interest in the - software to the public domain. We make this dedication for the - benefit of the public at large and to the detriment of our heirs and - successors. We intend this dedication to be an overt act of - relinquishment in perpetuity of all present and future rights to this - software under copyright law. - . - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - . - For more information, please refer to - -License: SIL-OPEN-FONT - This Font Software is licensed under the SIL Open Font License, - Version 1.1. - . - This license is copied below, and is also available with a FAQ at: - http://scripts.sil.org/OFL - . - SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 - . - PREAMBLE The goals of the Open Font License (OFL) are to stimulate - worldwide development of collaborative font projects, to support the font - creation efforts of academic and linguistic communities, and to provide - a free and open framework in which fonts may be shared and improved in - partnership with others. - . - The OFL allows the licensed fonts to be used, studied, modified and - redistributed freely as long as they are not sold by themselves. - The fonts, including any derivative works, can be bundled, embedded, - redistributed and/or sold with any software provided that any reserved - names are not used by derivative works. The fonts and derivatives, - however, cannot be released under any other type of license. The - requirement for fonts to remain under this license does not apply to - any document created using the fonts or their derivatives. - . - DEFINITIONS - "Font Software" refers to the set of files released by the Copyright - Holder(s) under this license and clearly marked as such. - This may include source files, build scripts and documentation. - . - "Reserved Font Name" refers to any names specified as such after the - copyright statement(s). - . - "Original Version" refers to the collection of Font Software components - as distributed by the Copyright Holder(s). - . - "Modified Version" refers to any derivative made by adding to, deleting, - or substituting ? in part or in whole ? - any of the components of the Original Version, by changing formats or - by porting the Font Software to a new environment. - . - "Author" refers to any designer, engineer, programmer, technical writer - or other person who contributed to the Font Software. - . - PERMISSION & CONDITIONS - . - Permission is hereby granted, free of charge, to any person obtaining a - copy of the Font Software, to use, study, copy, merge, embed, modify, - redistribute, and sell modified and unmodified copies of the Font - Software, subject to the following conditions: - . - 1) Neither the Font Software nor any of its individual components,in - Original or Modified Versions, may be sold by itself. - . - 2) Original or Modified Versions of the Font Software may be bundled, - redistributed and/or sold with any software, provided that each copy - contains the above copyright notice and this license. These can be - included either as stand-alone text files, human-readable headers or - in the appropriate machine-readable metadata fields within text or - binary files as long as those fields can be easily viewed by the user. - . - 3) No Modified Version of the Font Software may use the Reserved Font - Name(s) unless explicit written permission is granted by the - corresponding Copyright Holder. This restriction only applies to the - primary font name as presented to the users. - . - 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font - Software shall not be used to promote, endorse or advertise any - Modified Version, except to acknowledge the contribution(s) of the - Copyright Holder(s) and the Author(s) or with their explicit written - permission. - 5) The Font Software, modified or unmodified, in part or in whole, must - be distributed entirely under this license, and must not be distributed - under any other license. The requirement for fonts to remain under - this license does not apply to any document created using the Font - Software. - . - TERMINATION - This license becomes null and void if any of the above conditions are not met. - . - DISCLAIMER - THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE - COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL - DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF THE USE OR INABILITY - -License: GPL-2+ - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - . - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - . - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - . - On Debian systems, see /usr/share/common-licenses/GPL-2 for the full - text of the GPL version 2. - -License: CC-BY - Attribution 4.0 International - . - ======================================================================= - . - Creative Commons Corporation ("Creative Commons") is not a law firm and - does not provide legal services or legal advice. Distribution of - Creative Commons public licenses does not create a lawyer-client or - other relationship. Creative Commons makes its licenses and related - information available on an "as-is" basis. Creative Commons gives no - warranties regarding its licenses, any material licensed under their - terms and conditions, or any related information. Creative Commons - disclaims all liability for damages resulting from their use to the - fullest extent possible. - . - Using Creative Commons Public Licenses - . - Creative Commons public licenses provide a standard set of terms and - conditions that creators and other rights holders may use to share - original works of authorship and other material subject to copyright - and certain other rights specified in the public license below. The - following considerations are for informational purposes only, are not - exhaustive, and do not form part of our licenses. - . - Considerations for licensors: Our public licenses are - intended for use by those authorized to give the public - permission to use material in ways otherwise restricted by - copyright and certain other rights. Our licenses are - irrevocable. Licensors should read and understand the terms - and conditions of the license they choose before applying it. - Licensors should also secure all rights necessary before - applying our licenses so that the public can reuse the - material as expected. Licensors should clearly mark any - material not subject to the license. This includes other CC- - licensed material, or material used under an exception or - limitation to copyright. More considerations for licensors: - wiki.creativecommons.org/Considerations_for_licensors - . - Considerations for the public: By using one of our public - licenses, a licensor grants the public permission to use the - licensed material under specified terms and conditions. If - the licensor's permission is not necessary for any reason--for - example, because of any applicable exception or limitation to - copyright--then that use is not regulated by the license. Our - licenses grant only permissions under copyright and certain - other rights that a licensor has authority to grant. Use of - the licensed material may still be restricted for other - reasons, including because others have copyright or other - rights in the material. A licensor may make special requests, - such as asking that all changes be marked or described. - Although not required by our licenses, you are encouraged to - respect those requests where reasonable. More_considerations - for the public: - wiki.creativecommons.org/Considerations_for_licensees - . - ======================================================================= - . - Creative Commons Attribution 4.0 International Public License - . - By exercising the Licensed Rights (defined below), You accept and agree - to be bound by the terms and conditions of this Creative Commons - Attribution 4.0 International Public License ("Public License"). To the - extent this Public License may be interpreted as a contract, You are - granted the Licensed Rights in consideration of Your acceptance of - these terms and conditions, and the Licensor grants You such rights in - consideration of benefits the Licensor receives from making the - Licensed Material available under these terms and conditions. - . - . - Section 1 -- Definitions. - . - a. Adapted Material means material subject to Copyright and Similar - Rights that is derived from or based upon the Licensed Material - and in which the Licensed Material is translated, altered, - arranged, transformed, or otherwise modified in a manner requiring - permission under the Copyright and Similar Rights held by the - Licensor. For purposes of this Public License, where the Licensed - Material is a musical work, performance, or sound recording, - Adapted Material is always produced where the Licensed Material is - synched in timed relation with a moving image. - . - b. Adapter's License means the license You apply to Your Copyright - and Similar Rights in Your contributions to Adapted Material in - accordance with the terms and conditions of this Public License. - . - c. Copyright and Similar Rights means copyright and/or similar rights - closely related to copyright including, without limitation, - performance, broadcast, sound recording, and Sui Generis Database - Rights, without regard to how the rights are labeled or - categorized. For purposes of this Public License, the rights - specified in Section 2(b)(1)-(2) are not Copyright and Similar - Rights. - . - d. Effective Technological Measures means those measures that, in the - absence of proper authority, may not be circumvented under laws - fulfilling obligations under Article 11 of the WIPO Copyright - Treaty adopted on December 20, 1996, and/or similar international - agreements. - . - e. Exceptions and Limitations means fair use, fair dealing, and/or - any other exception or limitation to Copyright and Similar Rights - that applies to Your use of the Licensed Material. - . - f. Licensed Material means the artistic or literary work, database, - or other material to which the Licensor applied this Public - License. - . - g. Licensed Rights means the rights granted to You subject to the - terms and conditions of this Public License, which are limited to - all Copyright and Similar Rights that apply to Your use of the - Licensed Material and that the Licensor has authority to license. - . - h. Licensor means the individual(s) or entity(ies) granting rights - under this Public License. - . - i. Share means to provide material to the public by any means or - process that requires permission under the Licensed Rights, such - as reproduction, public display, public performance, distribution, - dissemination, communication, or importation, and to make material - available to the public including in ways that members of the - public may access the material from a place and at a time - individually chosen by them. - . - j. Sui Generis Database Rights means rights other than copyright - resulting from Directive 96/9/EC of the European Parliament and of - the Council of 11 March 1996 on the legal protection of databases, - as amended and/or succeeded, as well as other essentially - equivalent rights anywhere in the world. - . - k. You means the individual or entity exercising the Licensed Rights - under this Public License. Your has a corresponding meaning. - . - . - Section 2 -- Scope. - . - a. License grant. - . - 1. Subject to the terms and conditions of this Public License, - the Licensor hereby grants You a worldwide, royalty-free, - non-sublicensable, non-exclusive, irrevocable license to - exercise the Licensed Rights in the Licensed Material to: - . - a. reproduce and Share the Licensed Material, in whole or - in part; and - . - b. produce, reproduce, and Share Adapted Material. - . - 2. Exceptions and Limitations. For the avoidance of doubt, where - Exceptions and Limitations apply to Your use, this Public - License does not apply, and You do not need to comply with - its terms and conditions. - . - 3. Term. The term of this Public License is specified in Section - 6(a). - . - 4. Media and formats; technical modifications allowed. The - Licensor authorizes You to exercise the Licensed Rights in - all media and formats whether now known or hereafter created, - and to make technical modifications necessary to do so. The - Licensor waives and/or agrees not to assert any right or - authority to forbid You from making technical modifications - necessary to exercise the Licensed Rights, including - technical modifications necessary to circumvent Effective - Technological Measures. For purposes of this Public License, - simply making modifications authorized by this Section 2(a) - (4) never produces Adapted Material. - . - 5. Downstream recipients. - . - a. Offer from the Licensor -- Licensed Material. Every - recipient of the Licensed Material automatically - receives an offer from the Licensor to exercise the - Licensed Rights under the terms and conditions of this - Public License. - . - b. No downstream restrictions. You may not offer or impose - any additional or different terms or conditions on, or - apply any Effective Technological Measures to, the - Licensed Material if doing so restricts exercise of the - Licensed Rights by any recipient of the Licensed - Material. - . - 6. No endorsement. Nothing in this Public License constitutes or - may be construed as permission to assert or imply that You - are, or that Your use of the Licensed Material is, connected - with, or sponsored, endorsed, or granted official status by, - the Licensor or others designated to receive attribution as - provided in Section 3(a)(1)(A)(i). - . - b. Other rights. - . - 1. Moral rights, such as the right of integrity, are not - licensed under this Public License, nor are publicity, - privacy, and/or other similar personality rights; however, to - the extent possible, the Licensor waives and/or agrees not to - assert any such rights held by the Licensor to the limited - extent necessary to allow You to exercise the Licensed - Rights, but not otherwise. - . - 2. Patent and trademark rights are not licensed under this - Public License. - . - 3. To the extent possible, the Licensor waives any right to - collect royalties from You for the exercise of the Licensed - Rights, whether directly or through a collecting society - under any voluntary or waivable statutory or compulsory - licensing scheme. In all other cases the Licensor expressly - reserves any right to collect such royalties. - . - . - Section 3 -- License Conditions. - . - Your exercise of the Licensed Rights is expressly made subject to the - following conditions. - . - a. Attribution. - . - 1. If You Share the Licensed Material (including in modified - form), You must: - . - a. retain the following if it is supplied by the Licensor - with the Licensed Material: - . - i. identification of the creator(s) of the Licensed - Material and any others designated to receive - attribution, in any reasonable manner requested by - the Licensor (including by pseudonym if - designated); - . - ii. a copyright notice; - . - iii. a notice that refers to this Public License; - . - iv. a notice that refers to the disclaimer of - warranties; - . - v. a URI or hyperlink to the Licensed Material to the - extent reasonably practicable; - . - b. indicate if You modified the Licensed Material and - retain an indication of any previous modifications; and - . - c. indicate the Licensed Material is licensed under this - Public License, and include the text of, or the URI or - hyperlink to, this Public License. - . - 2. You may satisfy the conditions in Section 3(a)(1) in any - reasonable manner based on the medium, means, and context in - which You Share the Licensed Material. For example, it may be - reasonable to satisfy the conditions by providing a URI or - hyperlink to a resource that includes the required - information. - . - 3. If requested by the Licensor, You must remove any of the - information required by Section 3(a)(1)(A) to the extent - reasonably practicable. - . - 4. If You Share Adapted Material You produce, the Adapter's - License You apply must not prevent recipients of the Adapted - Material from complying with this Public License. - . - . - Section 4 -- Sui Generis Database Rights. - . - Where the Licensed Rights include Sui Generis Database Rights that - apply to Your use of the Licensed Material: - . - a. for the avoidance of doubt, Section 2(a)(1) grants You the right - to extract, reuse, reproduce, and Share all or a substantial - portion of the contents of the database; - . - b. if You include all or a substantial portion of the database - contents in a database in which You have Sui Generis Database - Rights, then the database in which You have Sui Generis Database - Rights (but not its individual contents) is Adapted Material; and - . - c. You must comply with the conditions in Section 3(a) if You Share - all or a substantial portion of the contents of the database. - . - For the avoidance of doubt, this Section 4 supplements and does not - replace Your obligations under this Public License where the Licensed - Rights include other Copyright and Similar Rights. - . - . - Section 5 -- Disclaimer of Warranties and Limitation of Liability. - . - a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE - EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS - AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF - ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, - IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, - WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR - PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, - ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT - KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT - ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. - . - b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE - TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, - NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, - INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, - COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR - USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN - ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR - DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR - IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. - . - c. The disclaimer of warranties and limitation of liability provided - above shall be interpreted in a manner that, to the extent - possible, most closely approximates an absolute disclaimer and - waiver of all liability. - . - . - Section 6 -- Term and Termination. - . - a. This Public License applies for the term of the Copyright and - Similar Rights licensed here. However, if You fail to comply with - this Public License, then Your rights under this Public License - terminate automatically. - . - b. Where Your right to use the Licensed Material has terminated under - Section 6(a), it reinstates: - . - 1. automatically as of the date the violation is cured, provided - it is cured within 30 days of Your discovery of the - violation; or - . - 2. upon express reinstatement by the Licensor. - . - For the avoidance of doubt, this Section 6(b) does not affect any - right the Licensor may have to seek remedies for Your violations - of this Public License. - . - c. For the avoidance of doubt, the Licensor may also offer the - Licensed Material under separate terms or conditions or stop - distributing the Licensed Material at any time; however, doing so - will not terminate this Public License. - . - d. Sections 1, 5, 6, 7, and 8 survive termination of this Public - License. - . - . - Section 7 -- Other Terms and Conditions. - . - a. The Licensor shall not be bound by any additional or different - terms or conditions communicated by You unless expressly agreed. - . - b. Any arrangements, understandings, or agreements regarding the - Licensed Material not stated herein are separate from and - independent of the terms and conditions of this Public License. - . - . - Section 8 -- Interpretation. - . - a. For the avoidance of doubt, this Public License does not, and - shall not be interpreted to, reduce, limit, restrict, or impose - conditions on any use of the Licensed Material that could lawfully - be made without permission under this Public License. - . - b. To the extent possible, if any provision of this Public License is - deemed unenforceable, it shall be automatically reformed to the - minimum extent necessary to make it enforceable. If the provision - cannot be reformed, it shall be severed from this Public License - without affecting the enforceability of the remaining terms and - conditions. - . - c. No term or condition of this Public License will be waived and no - failure to comply consented to unless expressly agreed to by the - Licensor. - . - d. Nothing in this Public License constitutes or may be interpreted - as a limitation upon, or waiver of, any privileges and immunities - that apply to the Licensor or You, including from the legal - processes of any jurisdiction or authority. - . - . - ======================================================================= - . - Creative Commons is not a party to its public licenses. - Notwithstanding, Creative Commons may elect to apply one of its public - licenses to material it publishes and in those instances will be - considered the "Licensor." Except for the limited purpose of indicating - that material is shared under a Creative Commons public license or as - otherwise permitted by the Creative Commons policies published at - creativecommons.org/policies, Creative Commons does not authorize the - use of the trademark "Creative Commons" or any other trademark or logo - of Creative Commons without its prior written consent including, - without limitation, in connection with any unauthorized modifications - to any of its public licenses or any other arrangements, - understandings, or agreements concerning use of licensed material. For - the avoidance of doubt, this paragraph does not form part of the public - licenses. - . - Creative Commons may be contacted at creativecommons.org. - -License: MPL-2.0 - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - . - On Debian systems, see /usr/share/common-licenses/MPL-2.0 for the full - text of the MPL version 2.0. - -License: Zlib - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - . - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - . - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. +License: OFL-1.1 -- cgit 1.4.1-3-g733a5 From 00c8306cdbf008ea60dd8f4418772e71a7f9ca6e Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 18 Aug 2022 16:03:55 +0200 Subject: import license changes --- LICENSES/Apache-2.0.txt | 73 ++++++++++++++++++++++++++++++++++++++++++++ LICENSES/BSD-2-Clause.txt | 9 ++++++ LICENSES/LicenseRef-TODO.txt | 2 -- LICENSES/MIT.txt | 9 ++++++ LICENSES/OFL-1.1.txt | 43 ++++++++++++++++++++++++++ 5 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 LICENSES/Apache-2.0.txt create mode 100644 LICENSES/BSD-2-Clause.txt delete mode 100644 LICENSES/LicenseRef-TODO.txt create mode 100644 LICENSES/MIT.txt create mode 100644 LICENSES/OFL-1.1.txt diff --git a/LICENSES/Apache-2.0.txt b/LICENSES/Apache-2.0.txt new file mode 100644 index 00000000000..137069b8238 --- /dev/null +++ b/LICENSES/Apache-2.0.txt @@ -0,0 +1,73 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSES/BSD-2-Clause.txt b/LICENSES/BSD-2-Clause.txt new file mode 100644 index 00000000000..5f662b354cd --- /dev/null +++ b/LICENSES/BSD-2-Clause.txt @@ -0,0 +1,9 @@ +Copyright (c) + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/LicenseRef-TODO.txt b/LICENSES/LicenseRef-TODO.txt deleted file mode 100644 index 7b193bf7d5e..00000000000 --- a/LICENSES/LicenseRef-TODO.txt +++ /dev/null @@ -1,2 +0,0 @@ -Temporary placeholder, only needed until we import the actual licensing -metadata. diff --git a/LICENSES/MIT.txt b/LICENSES/MIT.txt new file mode 100644 index 00000000000..2071b23b0e0 --- /dev/null +++ b/LICENSES/MIT.txt @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/LICENSES/OFL-1.1.txt b/LICENSES/OFL-1.1.txt new file mode 100644 index 00000000000..6fe84ee21eb --- /dev/null +++ b/LICENSES/OFL-1.1.txt @@ -0,0 +1,43 @@ +SIL OPEN FONT LICENSE + +Version 1.1 - 26 February 2007 + +PREAMBLE + +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. + +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. + +DEFINITIONS + +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). + +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. + +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS + +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. + +5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. + +TERMINATION + +This license becomes null and void if any of the above conditions are not met. + +DISCLAIMER + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. -- cgit 1.4.1-3-g733a5 From 2d968a142fb3ab2a69fa79b1e3b7af36f497a75b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 13 Aug 2022 14:00:23 +0200 Subject: Simplify rustdoc themes by relying more on CSS variables --- src/librustdoc/html/static/css/rustdoc.css | 61 +++++++++------------- src/librustdoc/html/static/css/themes/ayu.css | 65 ++---------------------- src/librustdoc/html/static/css/themes/dark.css | 65 +----------------------- src/librustdoc/html/static/css/themes/light.css | 67 +------------------------ 4 files changed, 30 insertions(+), 228 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 710ca3ee7c7..ed27df8898a 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -693,8 +693,13 @@ h2.location a { flex-grow: 1; margin: 0px; padding: 0px; + /* We use overflow-wrap: break-word for Safari, which doesn't recognize + `anywhere`: https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-wrap */ overflow-wrap: break-word; + /* Then override it with `anywhere`, which is required to make non-Safari browsers break + more aggressively when we want them to. */ overflow-wrap: anywhere; + background-color: var(--main-background-color); } .in-band > code, .in-band > .code-header { @@ -731,13 +736,13 @@ pre, .rustdoc.source .example-wrap { .docblock table td { padding: .5em; - border: 1px dashed; + border: 1px dashed var(--border-color); } .docblock table th { padding: .5em; text-align: left; - border: 1px solid; + border: 1px solid var(--border-color); } .fields + table { @@ -840,11 +845,11 @@ nav.main { text-align: center; } nav.main .current { - border-top: 1px solid; - border-bottom: 1px solid; + border-top: 1px solid var(--border-color); + border-bottom: 1px solid var(--border-color); } nav.main .separator { - border: 1px solid; + border: 1px solid var(--border-color); display: inline-block; height: 23px; margin: 0 20px; @@ -974,7 +979,7 @@ table, max-width: 100%; /* contents can overflow because of max-width limit, then show ellipsis */ text-overflow: ellipsis; - border: 1px solid; + border: 1px solid var(--border-color); border-radius: 4px; outline: none; cursor: pointer; @@ -1027,11 +1032,12 @@ so that we can apply CSS-filters to change the arrow color in themes */ -moz-box-sizing: border-box !important; box-sizing: border-box !important; outline: none; - border: 1px solid; + border: 1px solid var(--border-color); border-radius: 2px; padding: 8px; font-size: 1rem; width: 100%; + background-color: var(--button-background-color); } .search-results { @@ -1087,7 +1093,7 @@ so that we can apply CSS-filters to change the arrow color in themes */ display: block; margin-top: 7px; border-radius: 3px; - border: 1px solid; + border: 1px solid var(--border-color); font-size: 1rem; } @@ -1096,7 +1102,7 @@ so that we can apply CSS-filters to change the arrow color in themes */ content: ''; position: absolute; right: 11px; - border: solid; + border: solid var(--border-color); border-width: 1px 1px 0 0; display: inline-block; padding: 4px; @@ -1132,13 +1138,13 @@ so that we can apply CSS-filters to change the arrow color in themes */ text-align: center; display: block; margin: 10px 0; - border-bottom: 1px solid; + border-bottom: 1px solid var(--border-color); padding-bottom: 4px; margin-bottom: 6px; } #help-button span.bottom { clear: both; - border-top: 1px solid; + border-top: 1px solid var(--border-color); } .side-by-side { text-align: initial; @@ -1331,6 +1337,7 @@ h3.variant { border-radius: 6px; margin-left: 5px; font-size: 1rem; + border: 1px solid var(--border-color); } .tooltip.ignore::after { @@ -1496,7 +1503,7 @@ pre.rust { #source-sidebar > .title { font-size: 1.5rem; text-align: center; - border-bottom: 1px solid; + border-bottom: 1px solid var(--border-color); margin-bottom: 6px; } #sidebar-toggle > button { @@ -1524,11 +1531,12 @@ pre.rust { #copy-path { height: 34px; + background-color: var(--main-background-color); } #settings-menu > a, #help-button > button, #copy-path { padding: 5px; width: 33px; - border: 1px solid; + border: 1px solid var(--border-color); border-radius: 2px; cursor: pointer; } @@ -1539,6 +1547,7 @@ pre.rust { padding: 5px; height: 100%; display: block; + background-color: var(--button-background-color); } @keyframes rotating { @@ -1588,37 +1597,13 @@ input:checked + .slider { border: 0; } -#theme-choices { - display: none; - position: absolute; - left: 0; - top: 28px; - border: 1px solid; - border-radius: 3px; - z-index: 1; - cursor: pointer; -} - -#theme-choices > button { - border: none; - width: 100%; - padding: 4px 8px; - text-align: center; - background: rgba(0,0,0,0); - overflow-wrap: normal; -} - -#theme-choices > button:not(:first-child) { - border-top: 1px solid; -} - kbd { display: inline-block; padding: 3px 5px; font: 15px monospace; line-height: 10px; vertical-align: middle; - border: solid 1px; + border: solid 1px var(--border-color); border-radius: 3px; cursor: default; } diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 4dfb64abbeb..e7ccd402dd0 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -14,6 +14,8 @@ Original by Dempfi (https://github.com/dempfi/ayu) --scrollbar-thumb-background-color: #5c6773; --scrollbar-color: #5c6773 #24292f; --headings-border-bottom-color: #5c6773; + --border-color: #5c6773; + --button-background-color: #141920; } .slider { @@ -36,10 +38,6 @@ h4 { border: none; } -.in-band { - background-color: #0f1419; -} - .docblock code { color: #ffb454; } @@ -84,10 +82,6 @@ pre, .rustdoc.source .example-wrap { border-right: 1px solid #ffb44c; } -.docblock table td, .docblock table th { - border-color: #5c6773; -} - .search-results a:hover { background-color: #777; } @@ -151,13 +145,6 @@ pre, .rustdoc.source .example-wrap { pre.rust .comment { color: #788797; } pre.rust .doccomment { color: #a1ac88; } -nav.main .current { - border-top-color: #5c6773; - border-bottom-color: #5c6773; -} -nav.main .separator { - border: 1px solid #5c6773; -} a { color: #39AFD7; } @@ -182,17 +169,6 @@ details.rustdoc-toggle > summary::before { filter: invert(100%); } -.search-input { - background-color: #141920; - border-color: #424c57; -} - -#crate-search { - /* Without the `!important`, the border-color is ignored for ``... - It cannot be in the group above because `.search-input` has a different border color on - hover. */ - border-color: #d2d2d2 !important; -} #crate-search-div::after { /* match border-color; uses https://codepen.io/sosuke/pen/Pjoqqp */ filter: invert(94%) sepia(0%) saturate(721%) hue-rotate(255deg) brightness(90%) contrast(90%); @@ -175,10 +154,6 @@ details.rustdoc-toggle > summary::before { filter: invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg) brightness(100%) contrast(91%); } -.search-input { - border-color: #e0e0e0; -} - .search-input:focus { border-color: #008dfd; } @@ -296,11 +271,6 @@ pre.ignore:hover, .information:hover + pre.ignore { .notable-traits-tooltiptext { background-color: #111; - border-color: #777; -} - -.notable-traits-tooltiptext .notable { - border-bottom-color: #d2d2d2; } #titles > button:not(.selected) { @@ -317,23 +287,13 @@ pre.ignore:hover, .information:hover + pre.ignore { color: #888; } -@media (max-width: 700px) { - .sidebar-elems { - border-right-color: #000; - } -} - kbd { color: #000; background-color: #fafbfc; - border-color: #d1d5da; - border-bottom-color: #c6cbd1; box-shadow: inset 0 -1px 0 #c6cbd1; } #settings-menu > a, #help-button > button { - border-color: #e0e0e0; - background: #f0f0f0; color: #000; } @@ -342,11 +302,6 @@ kbd { border-color: #ffb900; } -.popover, .popover::before, -#help-button span.top, #help-button span.bottom { - border-color: #d2d2d2; -} - #copy-path { color: #999; } @@ -357,19 +312,6 @@ kbd { filter: invert(65%); } -#theme-choices { - border-color: #e0e0e0; - background-color: #353535; -} - -#theme-choices > button:not(:first-child) { - border-top-color: #e0e0e0; -} - -#theme-choices > button:hover, #theme-choices > button:focus { - background-color: #4e4e4e; -} - .search-results .result-name span.alias { color: #fff; } @@ -377,9 +319,6 @@ kbd { color: #ccc; } -#source-sidebar > .title { - border-bottom-color: #ccc; -} #source-sidebar div.files > a:hover, details.dir-entry summary:hover, #source-sidebar div.files > a:focus, details.dir-entry summary:focus { background-color: #444; diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 5698088c790..7139c199729 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -9,6 +9,8 @@ --scrollbar-thumb-background-color: rgba(36, 37, 39, 0.6); --scrollbar-color: rgba(36, 37, 39, 0.6) #d9d9d9; --headings-border-bottom-color: #ddd; + --border-color: #e0e0e0; + --button-background-color: #fff; } .slider { @@ -21,10 +23,6 @@ input:focus + .slider { box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3); } -.in-band { - background-color: white; -} - .rust-logo { /* This rule exists to force other themes to explicitly style the logo. * Rustdoc has a custom linter for this purpose. @@ -41,10 +39,6 @@ input:focus + .slider { background-color: #FDFFD3 !important; } -.docblock table td, .docblock table th { - border-color: #ddd; -} - .search-results a:hover { background-color: #ddd; } @@ -123,14 +117,6 @@ a.result-keyword:focus { background-color: #afc6e4; } .sidebar a.current.tymethod { color: #a67736; } .sidebar a.current.keyword { color: #356da4; } -nav.main .current { - border-top-color: #000; - border-bottom-color: #000; -} -nav.main .separator { - border: 1px solid #000; -} - a { color: #3873AD; } @@ -144,16 +130,6 @@ details.rustdoc-toggle > summary::before { color: #999; } -.search-input { - background-color: white; - border-color: #e0e0e0; -} -#crate-search { - /* Without the `!important`, the border-color is ignored for `