From b2c1c8f13a88be63ebe1907996bf806a91ec5680 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Thu, 12 Sep 2024 02:53:12 +0300 Subject: Stabilize `std::io::ErrorKind::QuotaExceeded` Also drop "Filesystem" from its name --- src/tools/miri/src/shims/io_error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/tools') diff --git a/src/tools/miri/src/shims/io_error.rs b/src/tools/miri/src/shims/io_error.rs index 38aa181cb4f..1a95ae1e7d4 100644 --- a/src/tools/miri/src/shims/io_error.rs +++ b/src/tools/miri/src/shims/io_error.rs @@ -43,7 +43,7 @@ const UNIX_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = { ("ECONNREFUSED", ConnectionRefused), ("ECONNRESET", ConnectionReset), ("EDEADLK", Deadlock), - ("EDQUOT", FilesystemQuotaExceeded), + ("EDQUOT", QuotaExceeded), ("EEXIST", AlreadyExists), ("EFBIG", FileTooLarge), ("EHOSTUNREACH", HostUnreachable), -- cgit 1.4.1-3-g733a5 From 95a51384820eb3d599618b4f74e5edf375885f40 Mon Sep 17 00:00:00 2001 From: Johannes Hostert Date: Sat, 26 Oct 2024 16:35:56 +0200 Subject: Add benchmark showing effectivity of subtree skipping --- src/tools/miri/bench-cargo-miri/string-replace/Cargo.lock | 7 +++++++ src/tools/miri/bench-cargo-miri/string-replace/Cargo.toml | 8 ++++++++ src/tools/miri/bench-cargo-miri/string-replace/data.json | 1 + src/tools/miri/bench-cargo-miri/string-replace/src/main.rs | 7 +++++++ 4 files changed, 23 insertions(+) create mode 100644 src/tools/miri/bench-cargo-miri/string-replace/Cargo.lock create mode 100644 src/tools/miri/bench-cargo-miri/string-replace/Cargo.toml create mode 100644 src/tools/miri/bench-cargo-miri/string-replace/data.json create mode 100644 src/tools/miri/bench-cargo-miri/string-replace/src/main.rs (limited to 'src/tools') diff --git a/src/tools/miri/bench-cargo-miri/string-replace/Cargo.lock b/src/tools/miri/bench-cargo-miri/string-replace/Cargo.lock new file mode 100644 index 00000000000..443115c1265 --- /dev/null +++ b/src/tools/miri/bench-cargo-miri/string-replace/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "string-replace" +version = "0.1.0" diff --git a/src/tools/miri/bench-cargo-miri/string-replace/Cargo.toml b/src/tools/miri/bench-cargo-miri/string-replace/Cargo.toml new file mode 100644 index 00000000000..f0785cd693e --- /dev/null +++ b/src/tools/miri/bench-cargo-miri/string-replace/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "string-replace" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/tools/miri/bench-cargo-miri/string-replace/data.json b/src/tools/miri/bench-cargo-miri/string-replace/data.json new file mode 100644 index 00000000000..7e074cd6954 --- /dev/null +++ b/src/tools/miri/bench-cargo-miri/string-replace/data.json @@ -0,0 +1 @@ +[{"_id":"6724e6fc58417687afba2b85","index":0,"guid":"5c1bd108-2ee2-40bd-bce8-895c206409df","isActive":true,"balance":"$2,927.88","picture":"http://placehold.it/32x32","age":40,"eyeColor":"green","name":"Wynn Bradshaw","gender":"male","company":"ROTODYNE","email":"wynnbradshaw@rotodyne.com","phone":"+1 (904) 559-3130","address":"287 Bergen Avenue, Sperryville, Alaska, 5392","about":"Adipisicing fugiat aute adipisicing qui esse cillum. Lorem consequat consectetur voluptate id pariatur nostrud incididunt aliquip incididunt laboris aliqua. Magna nulla adipisicing cupidatat ea velit aliquip magna duis duis sunt ipsum. Cillum labore mollit fugiat tempor dolor sit.\r\n","registered":"2017-01-26T01:28:10 -01:00","latitude":46.089504,"longitude":51.763723,"greeting":"Hello, Wynn Bradshaw! You have 6 unread messages.","favoriteFruit":"banana"},{"_id":"6724e6fce8619d86c0389ccf","index":1,"guid":"ced7fbb7-3b1a-419b-9fc7-d47582bbb3ea","isActive":true,"balance":"$1,856.38","picture":"http://placehold.it/32x32","age":21,"eyeColor":"brown","name":"Olsen Larsen","gender":"male","company":"VERBUS","email":"olsenlarsen@verbus.com","phone":"+1 (936) 480-3749","address":"370 Losee Terrace, Churchill, Maine, 4040","about":"Consequat Lorem in laboris fugiat veniam tempor eiusmod eu incididunt enim do et qui. Sit commodo eu excepteur cillum ex tempor commodo ex ex laboris esse. Aute aute nulla dolore dolor do. Irure esse proident nostrud non. Incididunt velit reprehenderit incididunt laboris do. Consequat nulla est id ex veniam tempor. Sit Lorem magna cillum aliquip irure quis sit minim anim.\r\n","registered":"2016-07-12T02:08:39 -02:00","latitude":-12.843628,"longitude":-124.143829,"greeting":"Hello, Olsen Larsen! You have 1 unread messages.","favoriteFruit":"apple"},{"_id":"6724e6fc01b471965ea560cf","index":2,"guid":"21fde9a3-13ba-46be-baed-fb503f668b9e","isActive":false,"balance":"$2,025.88","picture":"http://placehold.it/32x32","age":29,"eyeColor":"green","name":"Ramirez Kinney","gender":"male","company":"QUAREX","email":"ramirezkinney@quarex.com","phone":"+1 (852) 447-2930","address":"986 Cornelia Street, Oberlin, Texas, 362","about":"Minim ea proident quis eiusmod aliquip duis excepteur velit minim aute cupidatat. Esse qui ex aliquip laborum id reprehenderit. Anim dolore commodo deserunt laborum nulla duis. Sint quis anim mollit fugiat sit incididunt reprehenderit occaecat aliqua dolor. Ullamco ipsum eiusmod incididunt proident qui exercitation adipisicing voluptate elit aliquip. Tempor duis aute incididunt adipisicing.\r\n","registered":"2016-02-23T05:34:14 -01:00","latitude":-56.21645,"longitude":44.048129,"greeting":"Hello, Ramirez Kinney! You have 9 unread messages.","favoriteFruit":"banana"},{"_id":"6724e6fc3ea8e4182b9e170f","index":3,"guid":"46b20637-eecc-40db-87d7-03da9bcd1cea","isActive":true,"balance":"$3,399.31","picture":"http://placehold.it/32x32","age":39,"eyeColor":"brown","name":"Hansen Kaufman","gender":"male","company":"EVENTAGE","email":"hansenkaufman@eventage.com","phone":"+1 (827) 483-2303","address":"916 Brighton Court, Sunbury, New Mexico, 3804","about":"Nisi in voluptate aute ullamco ipsum proident fugiat veniam anim reprehenderit. In ad irure dolor labore culpa incididunt veniam mollit Lorem deserunt cupidatat incididunt. Aliquip aliquip proident ut culpa.\r\n","registered":"2023-10-18T07:03:48 -02:00","latitude":-40.239135,"longitude":49.802049,"greeting":"Hello, Hansen Kaufman! You have 10 unread messages.","favoriteFruit":"apple"},{"_id":"6724e6fc721f83a10cf2aa37","index":4,"guid":"3d23743b-1e82-474e-8f7a-855fa46170d1","isActive":false,"balance":"$1,967.87","picture":"http://placehold.it/32x32","age":35,"eyeColor":"green","name":"Imelda Stephens","gender":"female","company":"OHMNET","email":"imeldastephens@ohmnet.com","phone":"+1 (893) 523-2400","address":"391 Wilson Street, Glidden, Kansas, 7226","about":"Officia sunt magna adipisicing id exercitation deserunt deserunt aliquip excepteur Lorem enim fugiat. Nulla culpa ut cupidatat excepteur do deserunt labore id eu laboris ullamco adipisicing ad. Et non nisi adipisicing minim aliquip ea ut qui adipisicing do laboris ex dolore duis.\r\n","registered":"2020-10-20T07:03:38 -02:00","latitude":0.348698,"longitude":-157.961956,"greeting":"Hello, Imelda Stephens! You have 2 unread messages.","favoriteFruit":"strawberry"},{"_id":"6724e6fc7ad7274b9f4c406c","index":5,"guid":"626292b1-ae84-4887-9e29-78e548cd24e6","isActive":true,"balance":"$1,577.44","picture":"http://placehold.it/32x32","age":40,"eyeColor":"brown","name":"Lynne Jarvis","gender":"female","company":"CORECOM","email":"lynnejarvis@corecom.com","phone":"+1 (899) 556-3876","address":"465 National Drive, Davenport, Palau, 9786","about":"Aliquip elit dolore sint quis do laboris exercitation elit aliqua eiusmod. Excepteur ad aliqua eiusmod incididunt tempor laboris officia consectetur sit. Cupidatat voluptate deserunt ut consectetur qui laborum duis elit incididunt occaecat laborum. Mollit aute velit officia amet aute minim fugiat sit laborum Lorem deserunt in. Exercitation eu sunt nulla adipisicing quis ea aute est. Lorem ea cillum ad labore quis minim et est laboris deserunt proident. Amet ut tempor laborum occaecat exercitation ullamco laborum adipisicing fugiat ea voluptate quis fugiat.\r\n","registered":"2018-11-03T03:53:15 -01:00","latitude":89.827087,"longitude":-136.882799,"greeting":"Hello, Lynne Jarvis! You have 3 unread messages.","favoriteFruit":"strawberry"},{"_id":"6724e6fcef1a1db2cf170762","index":6,"guid":"b8777c06-b90f-49a4-8737-96712fc504a3","isActive":false,"balance":"$2,285.03","picture":"http://placehold.it/32x32","age":37,"eyeColor":"green","name":"Price Bolton","gender":"male","company":"IMANT","email":"pricebolton@imant.com","phone":"+1 (825) 424-2873","address":"237 Aberdeen Street, Sattley, Montana, 2918","about":"Non cillum irure fugiat consequat ad ex. Magna magna tempor excepteur irure quis. Duis in laboris ipsum adipisicing culpa magna reprehenderit nisi incididunt est veniam quis. Labore culpa ut culpa veniam est est consectetur ipsum ex esse.\r\n","registered":"2014-04-26T01:20:19 -02:00","latitude":70.349258,"longitude":126.810102,"greeting":"Hello, Price Bolton! You have 10 unread messages.","favoriteFruit":"banana"},{"_id":"6724e6fc8bcb952208c159f9","index":7,"guid":"a4e6c6c8-3fe3-42de-ae28-79c16956d309","isActive":false,"balance":"$1,298.07","picture":"http://placehold.it/32x32","age":28,"eyeColor":"blue","name":"Gretchen Wynn","gender":"female","company":"TERASCAPE","email":"gretchenwynn@terascape.com","phone":"+1 (882) 447-2895","address":"973 Suydam Place, Shindler, Nebraska, 8094","about":"Anim mollit labore magna proident ipsum culpa enim deserunt dolore sunt veniam fugiat. Ad fugiat cupidatat nisi commodo dolore duis commodo nostrud est. Enim proident ullamco non adipisicing magna consequat mollit ad reprehenderit laboris. Ex quis duis anim id non commodo amet sunt est magna officia.\r\n","registered":"2021-08-13T08:51:32 -02:00","latitude":14.551848,"longitude":-27.142242,"greeting":"Hello, Gretchen Wynn! You have 7 unread messages.","favoriteFruit":"apple"},{"_id":"6724e6fcc8243c2dfa47f5d4","index":8,"guid":"27df20d5-c1d8-419b-ad38-bdd1e6094775","isActive":true,"balance":"$3,005.40","picture":"http://placehold.it/32x32","age":33,"eyeColor":"blue","name":"Chen Travis","gender":"male","company":"MEMORA","email":"chentravis@memora.com","phone":"+1 (980) 500-2406","address":"182 Dahlgreen Place, Baker, South Carolina, 9817","about":"Ad nisi consequat aliquip eiusmod aute pariatur est sint magna. Ad magna anim esse qui Lorem nulla veniam dolore eiusmod. Cillum consequat sit aliqua est proident exercitation eiusmod irure. Minim eu laboris ad incididunt enim sunt. Sunt in excepteur aute non tempor irure mollit laboris. Eu et duis ullamco dolor sint occaecat officia culpa ipsum anim anim eu veniam aliquip. Exercitation ipsum dolor sint cillum duis incididunt minim quis irure enim reprehenderit do do incididunt.\r\n","registered":"2019-09-01T02:57:37 -02:00","latitude":25.442301,"longitude":48.381036,"greeting":"Hello, Chen Travis! You have 1 unread messages.","favoriteFruit":"banana"}] \ No newline at end of file diff --git a/src/tools/miri/bench-cargo-miri/string-replace/src/main.rs b/src/tools/miri/bench-cargo-miri/string-replace/src/main.rs new file mode 100644 index 00000000000..73bf4a850e4 --- /dev/null +++ b/src/tools/miri/bench-cargo-miri/string-replace/src/main.rs @@ -0,0 +1,7 @@ +const TCB_INFO_JSON: &str = include_str!("../data.json"); + +fn main() { + let tcb_json = TCB_INFO_JSON; + let bad_tcb_json = tcb_json.replace("female", "male"); + std::hint::black_box(bad_tcb_json); +} -- cgit 1.4.1-3-g733a5 From 440080407219f4ad413fcc4819323d0ba920c440 Mon Sep 17 00:00:00 2001 From: tiif Date: Mon, 18 Nov 2024 02:17:36 +0800 Subject: Refactor AnonSocket::read/write --- src/tools/miri/src/shims/unix/unnamed_socket.rs | 124 +++++++++++++++--------- 1 file changed, 80 insertions(+), 44 deletions(-) (limited to 'src/tools') diff --git a/src/tools/miri/src/shims/unix/unnamed_socket.rs b/src/tools/miri/src/shims/unix/unnamed_socket.rs index 8ccce7c1986..36575f4b5fb 100644 --- a/src/tools/miri/src/shims/unix/unnamed_socket.rs +++ b/src/tools/miri/src/shims/unix/unnamed_socket.rs @@ -146,8 +146,7 @@ impl FileDescription for AnonSocket { // corresponding ErrorKind variant. throw_unsup_format!("reading from the write end of a pipe"); }; - let mut readbuf = readbuf.borrow_mut(); - if readbuf.buf.is_empty() { + if readbuf.borrow().buf.is_empty() { if self.peer_fd().upgrade().is_none() { // Socketpair with no peer and empty buffer. // 0 bytes successfully read indicates end-of-file. @@ -167,31 +166,8 @@ impl FileDescription for AnonSocket { } } } - - // Synchronize with all previous writes to this buffer. - // FIXME: this over-synchronizes; a more precise approach would be to - // only sync with the writes whose data we will read. - ecx.acquire_clock(&readbuf.clock); - - // Do full read / partial read based on the space available. - // Conveniently, `read` exists on `VecDeque` and has exactly the desired behavior. - let actual_read_size = readbuf.buf.read(&mut bytes).unwrap(); - - // Need to drop before others can access the readbuf again. - drop(readbuf); - - // A notification should be provided for the peer file description even when it can - // only write 1 byte. This implementation is not compliant with the actual Linux kernel - // implementation. For optimization reasons, the kernel will only mark the file description - // as "writable" when it can write more than a certain number of bytes. Since we - // don't know what that *certain number* is, we will provide a notification every time - // a read is successful. This might result in our epoll emulation providing more - // notifications than the real system. - if let Some(peer_fd) = self.peer_fd().upgrade() { - ecx.check_and_update_readiness(&peer_fd)?; - } - - ecx.return_read_success(ptr, &bytes, actual_read_size, dest) + // TODO: We might need to decide what to do if peer_fd is closed when read is blocked. + anonsocket_read(self, self.peer_fd().upgrade(), &mut bytes, ptr, dest, ecx) } fn write<'tcx>( @@ -221,9 +197,8 @@ impl FileDescription for AnonSocket { // corresponding ErrorKind variant. throw_unsup_format!("writing to the reading end of a pipe"); }; - let mut writebuf = writebuf.borrow_mut(); - let data_size = writebuf.buf.len(); - let available_space = MAX_SOCKETPAIR_BUFFER_CAPACITY.strict_sub(data_size); + let available_space = + MAX_SOCKETPAIR_BUFFER_CAPACITY.strict_sub(writebuf.borrow().buf.len()); if available_space == 0 { if self.is_nonblock { // Non-blocking socketpair with a full buffer. @@ -233,24 +208,85 @@ impl FileDescription for AnonSocket { throw_unsup_format!("socketpair/pipe/pipe2 write: blocking isn't supported yet"); } } - // Remember this clock so `read` can synchronize with us. - ecx.release_clock(|clock| { - writebuf.clock.join(clock); - }); - // Do full write / partial write based on the space available. - let actual_write_size = len.min(available_space); - let bytes = ecx.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(len))?; - writebuf.buf.extend(&bytes[..actual_write_size]); + anonsocket_write(available_space, &peer_fd, ptr, len, dest, ecx) + } +} - // Need to stop accessing peer_fd so that it can be notified. - drop(writebuf); +/// Write to AnonSocket based on the space available and return the written byte size. +fn anonsocket_write<'tcx>( + available_space: usize, + peer_fd: &FileDescriptionRef, + ptr: Pointer, + len: usize, + dest: &MPlaceTy<'tcx>, + ecx: &mut MiriInterpCx<'tcx>, +) -> InterpResult<'tcx> { + let Some(writebuf) = &peer_fd.downcast::().unwrap().readbuf else { + // FIXME: This should return EBADF, but there's no nice way to do that as there's no + // corresponding ErrorKind variant. + throw_unsup_format!("writing to the reading end of a pipe") + }; + let mut writebuf = writebuf.borrow_mut(); + + // Remember this clock so `read` can synchronize with us. + ecx.release_clock(|clock| { + writebuf.clock.join(clock); + }); + // Do full write / partial write based on the space available. + let actual_write_size = len.min(available_space); + let bytes = ecx.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(len))?; + writebuf.buf.extend(&bytes[..actual_write_size]); + + // Need to stop accessing peer_fd so that it can be notified. + drop(writebuf); + + // Notification should be provided for peer fd as it became readable. + // The kernel does this even if the fd was already readable before, so we follow suit. + ecx.check_and_update_readiness(peer_fd)?; + + ecx.return_write_success(actual_write_size, dest) +} - // Notification should be provided for peer fd as it became readable. - // The kernel does this even if the fd was already readable before, so we follow suit. +/// Read from AnonSocket and return the number of bytes read. +fn anonsocket_read<'tcx>( + anonsocket: &AnonSocket, + peer_fd: Option, + bytes: &mut [u8], + ptr: Pointer, + dest: &MPlaceTy<'tcx>, + ecx: &mut MiriInterpCx<'tcx>, +) -> InterpResult<'tcx> { + let Some(readbuf) = &anonsocket.readbuf else { + // FIXME: This should return EBADF, but there's no nice way to do that as there's no + // corresponding ErrorKind variant. + throw_unsup_format!("reading from the write end of a pipe") + }; + let mut readbuf = readbuf.borrow_mut(); + + // Synchronize with all previous writes to this buffer. + // FIXME: this over-synchronizes; a more precise approach would be to + // only sync with the writes whose data we will read. + ecx.acquire_clock(&readbuf.clock); + + // Do full read / partial read based on the space available. + // Conveniently, `read` exists on `VecDeque` and has exactly the desired behavior. + let actual_read_size = readbuf.buf.read(bytes).unwrap(); + + // Need to drop before others can access the readbuf again. + drop(readbuf); + + // A notification should be provided for the peer file description even when it can + // only write 1 byte. This implementation is not compliant with the actual Linux kernel + // implementation. For optimization reasons, the kernel will only mark the file description + // as "writable" when it can write more than a certain number of bytes. Since we + // don't know what that *certain number* is, we will provide a notification every time + // a read is successful. This might result in our epoll emulation providing more + // notifications than the real system. + if let Some(peer_fd) = peer_fd { ecx.check_and_update_readiness(&peer_fd)?; - - ecx.return_write_success(actual_write_size, dest) } + + ecx.return_read_success(ptr, bytes, actual_read_size, dest) } impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} -- cgit 1.4.1-3-g733a5 From 6af006e988a8a522fbfac8dfdb6540fe001ebdf4 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Thu, 21 Nov 2024 11:44:30 -0800 Subject: Fill out Windows error mapping table --- src/tools/miri/src/shims/io_error.rs | 63 ++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 3 deletions(-) (limited to 'src/tools') diff --git a/src/tools/miri/src/shims/io_error.rs b/src/tools/miri/src/shims/io_error.rs index 0cbb4850b7f..c29469f1edd 100644 --- a/src/tools/miri/src/shims/io_error.rs +++ b/src/tools/miri/src/shims/io_error.rs @@ -82,11 +82,68 @@ const UNIX_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = { // . const WINDOWS_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = { use std::io::ErrorKind::*; - // FIXME: this is still incomplete. &[ - ("ERROR_ACCESS_DENIED", PermissionDenied), - ("ERROR_FILE_NOT_FOUND", NotFound), + ("WSAEADDRINUSE", AddrInUse), + ("WSAEADDRNOTAVAIL", AddrNotAvailable), + ("ERROR_ALREADY_EXISTS", AlreadyExists), + ("ERROR_FILE_EXISTS", AlreadyExists), + ("ERROR_NO_DATA", BrokenPipe), + ("WSAECONNABORTED", ConnectionAborted), + ("WSAECONNREFUSED", ConnectionRefused), + ("WSAECONNRESET", ConnectionReset), + ("ERROR_NOT_SAME_DEVICE", CrossesDevices), + ("ERROR_POSSIBLE_DEADLOCK", Deadlock), + ("ERROR_DIR_NOT_EMPTY", DirectoryNotEmpty), + ("ERROR_CANT_RESOLVE_FILENAME", FilesystemLoop), + ("ERROR_DISK_QUOTA_EXCEEDED", FilesystemQuotaExceeded), + ("WSAEDQUOT", FilesystemQuotaExceeded), + ("ERROR_FILE_TOO_LARGE", FileTooLarge), + ("ERROR_HOST_UNREACHABLE", HostUnreachable), + ("WSAEHOSTUNREACH", HostUnreachable), + ("ERROR_INVALID_NAME", InvalidFilename), + ("ERROR_BAD_PATHNAME", InvalidFilename), + ("ERROR_FILENAME_EXCED_RANGE", InvalidFilename), ("ERROR_INVALID_PARAMETER", InvalidInput), + ("WSAEINVAL", InvalidInput), + ("ERROR_DIRECTORY_NOT_SUPPORTED", IsADirectory), + ("WSAENETDOWN", NetworkDown), + ("ERROR_NETWORK_UNREACHABLE", NetworkUnreachable), + ("WSAENETUNREACH", NetworkUnreachable), + ("ERROR_DIRECTORY", NotADirectory), + ("WSAENOTCONN", NotConnected), + ("ERROR_FILE_NOT_FOUND", NotFound), + ("ERROR_PATH_NOT_FOUND", NotFound), + ("ERROR_INVALID_DRIVE", NotFound), + ("ERROR_BAD_NETPATH", NotFound), + ("ERROR_BAD_NET_NAME", NotFound), + ("ERROR_SEEK_ON_DEVICE", NotSeekable), + ("ERROR_NOT_ENOUGH_MEMORY", OutOfMemory), + ("ERROR_OUTOFMEMORY", OutOfMemory), + ("ERROR_ACCESS_DENIED", PermissionDenied), + ("WSAEACCES", PermissionDenied), + ("ERROR_WRITE_PROTECT", ReadOnlyFilesystem), + ("ERROR_BUSY", ResourceBusy), + ("ERROR_DISK_FULL", StorageFull), + ("ERROR_HANDLE_DISK_FULL", StorageFull), + ("WAIT_TIMEOUT", TimedOut), + ("WSAETIMEDOUT", TimedOut), + ("ERROR_DRIVER_CANCEL_TIMEOUT", TimedOut), + ("ERROR_OPERATION_ABORTED", TimedOut), + ("ERROR_SERVICE_REQUEST_TIMEOUT", TimedOut), + ("ERROR_COUNTER_TIMEOUT", TimedOut), + ("ERROR_TIMEOUT", TimedOut), + ("ERROR_RESOURCE_CALL_TIMED_OUT", TimedOut), + ("ERROR_CTX_MODEM_RESPONSE_TIMEOUT", TimedOut), + ("ERROR_CTX_CLIENT_QUERY_TIMEOUT", TimedOut), + ("FRS_ERR_SYSVOL_POPULATE_TIMEOUT", TimedOut), + ("ERROR_DS_TIMELIMIT_EXCEEDED", TimedOut), + ("DNS_ERROR_RECORD_TIMED_OUT", TimedOut), + ("ERROR_IPSEC_IKE_TIMED_OUT", TimedOut), + ("ERROR_RUNLEVEL_SWITCH_TIMEOUT", TimedOut), + ("ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT", TimedOut), + ("ERROR_TOO_MANY_LINKS", TooManyLinks), + ("ERROR_CALL_NOT_IMPLEMENTED", Unsupported), + ("WSAEWOULDBLOCK", WouldBlock), ] }; -- cgit 1.4.1-3-g733a5 From 7d38c51555cf4c77858f399846b6ca20d7d29ede Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 21 Nov 2024 22:27:43 +0100 Subject: eventfd: comment tweaks --- src/tools/miri/src/shims/unix/linux/eventfd.rs | 18 +++++++++++------- .../tests/fail-dep/libc/eventfd_block_read_twice.rs | 2 +- .../tests/fail-dep/libc/eventfd_block_write_twice.rs | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) (limited to 'src/tools') diff --git a/src/tools/miri/src/shims/unix/linux/eventfd.rs b/src/tools/miri/src/shims/unix/linux/eventfd.rs index 63b7d37b13e..2ec3d792d94 100644 --- a/src/tools/miri/src/shims/unix/linux/eventfd.rs +++ b/src/tools/miri/src/shims/unix/linux/eventfd.rs @@ -211,10 +211,10 @@ fn eventfd_write<'tcx>( eventfd.clock.borrow_mut().join(clock); }); - // When this function is called, the addition is guaranteed to not exceed u64::MAX - 1. + // Store new counter value. eventfd.counter.set(new_count); - // When any of the event happened, we check and update the status of all supported event + // The state changed; we check and update the status of all supported event // types for current file description. ecx.check_and_update_readiness(&eventfd_ref)?; @@ -228,10 +228,11 @@ fn eventfd_write<'tcx>( ecx.unblock_thread(thread_id, BlockReason::Eventfd)?; } - // Return how many bytes we wrote. + // Return how many bytes we consumed from the user-provided buffer. return ecx.write_int(buf_place.layout.size.bytes(), dest); } None | Some(u64::MAX) => { + // We can't update the state, so we have to block. if eventfd.is_nonblock { return ecx.set_last_error_and_return(ErrorKind::WouldBlock, dest); } @@ -251,6 +252,7 @@ fn eventfd_write<'tcx>( weak_eventfd: WeakFileDescriptionRef, } @unblock = |this| { + // When we get unblocked, try again. eventfd_write(num, buf_place, &dest, weak_eventfd, this) } ), @@ -276,9 +278,10 @@ fn eventfd_read<'tcx>( // an eventfd file description. let eventfd = eventfd_ref.downcast::().unwrap(); - // Block when counter == 0. + // Set counter to 0, get old value. let counter = eventfd.counter.replace(0); + // Block when counter == 0. if counter == 0 { if eventfd.is_nonblock { return ecx.set_last_error_and_return(ErrorKind::WouldBlock, dest); @@ -297,6 +300,7 @@ fn eventfd_read<'tcx>( weak_eventfd: WeakFileDescriptionRef, } @unblock = |this| { + // When we get unblocked, try again. eventfd_read(buf_place, &dest, weak_eventfd, this) } ), @@ -305,10 +309,10 @@ fn eventfd_read<'tcx>( // Synchronize with all prior `write` calls to this FD. ecx.acquire_clock(&eventfd.clock.borrow()); - // Give old counter value to userspace, and set counter value to 0. + // Return old counter value into user-space buffer. ecx.write_int(counter, &buf_place)?; - // When any of the events happened, we check and update the status of all supported event + // The state changed; we check and update the status of all supported event // types for current file description. ecx.check_and_update_readiness(&eventfd_ref)?; @@ -322,7 +326,7 @@ fn eventfd_read<'tcx>( ecx.unblock_thread(thread_id, BlockReason::Eventfd)?; } - // Tell userspace how many bytes we read. + // Tell userspace how many bytes we put into the buffer. return ecx.write_int(buf_place.layout.size.bytes(), dest); } interp_ok(()) diff --git a/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.rs b/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.rs index 65d29b2c6ba..111ca86a9b6 100644 --- a/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.rs +++ b/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.rs @@ -14,7 +14,7 @@ use std::thread; // 2. Thread 2 blocks. // 3. Thread 3 unblocks both thread 1 and thread 2. // 4. Thread 1 reads. -// 5. Thread 2's `read` deadlocked. +// 5. Thread 2's `read` can neber complete -> deadlocked. fn main() { // eventfd write will block when EFD_NONBLOCK flag is clear diff --git a/src/tools/miri/tests/fail-dep/libc/eventfd_block_write_twice.rs b/src/tools/miri/tests/fail-dep/libc/eventfd_block_write_twice.rs index f9d34d2fb58..2212d6c7eb5 100644 --- a/src/tools/miri/tests/fail-dep/libc/eventfd_block_write_twice.rs +++ b/src/tools/miri/tests/fail-dep/libc/eventfd_block_write_twice.rs @@ -14,7 +14,7 @@ use std::thread; // 2. Thread 2 blocks. // 3. Thread 3 unblocks both thread 1 and thread 2. // 4. Thread 1 writes u64::MAX. -// 5. Thread 2's `write` deadlocked. +// 5. Thread 2's `write` can never complete -> deadlocked. fn main() { // eventfd write will block when EFD_NONBLOCK flag is clear // and the addition caused counter to exceed u64::MAX - 1. -- cgit 1.4.1-3-g733a5 From 0a7e63a529c0c97e100f040fd34217e4b9d8143d Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Thu, 21 Nov 2024 13:36:42 -0800 Subject: Add comment about multiple errors to one ErrorKind --- src/tools/miri/src/shims/io_error.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/tools') diff --git a/src/tools/miri/src/shims/io_error.rs b/src/tools/miri/src/shims/io_error.rs index c29469f1edd..f67787e83f6 100644 --- a/src/tools/miri/src/shims/io_error.rs +++ b/src/tools/miri/src/shims/io_error.rs @@ -82,6 +82,10 @@ const UNIX_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = { // . const WINDOWS_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = { use std::io::ErrorKind::*; + // It's common for multiple error codes to map to the same io::ErrorKind. We have all for the + // forwards mapping; only the first one will be used for the backwards mapping. + // Slightly arbitrarily, we prefer non-WSA and the most generic sounding variant for backwards + // mapping. &[ ("WSAEADDRINUSE", AddrInUse), ("WSAEADDRNOTAVAIL", AddrNotAvailable), -- cgit 1.4.1-3-g733a5 From f77817a701c291b94fe6da25c4865bc50a8fcb1d Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Fri, 22 Nov 2024 05:20:39 +0000 Subject: Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/tools') diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index effed0cd180..e5812ae2603 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -2d0ea7956c45de6e421fd579e2ded27be405dec6 +5d3c6ee9b34989595d2a72b79e61ca37e949d757 -- cgit 1.4.1-3-g733a5 From 33f4d2ee61cedc12dd8119894c15e169b075cc46 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 21 Nov 2024 22:28:50 +0100 Subject: epoll: fix comment typo --- src/tools/miri/src/shims/unix/linux/epoll.rs | 2 +- src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/tools') diff --git a/src/tools/miri/src/shims/unix/linux/epoll.rs b/src/tools/miri/src/shims/unix/linux/epoll.rs index de108665e9f..b20b12528db 100644 --- a/src/tools/miri/src/shims/unix/linux/epoll.rs +++ b/src/tools/miri/src/shims/unix/linux/epoll.rs @@ -539,7 +539,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { )?; if is_updated { // Edge-triggered notification only notify one thread even if there are - // multiple threads block on the same epfd. + // multiple threads blocked on the same epfd. // This unwrap can never fail because if the current epoll instance were // closed, the upgrade of weak_epoll_interest diff --git a/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.rs b/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.rs index 111ca86a9b6..a9bb4c7eba8 100644 --- a/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.rs +++ b/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.rs @@ -14,7 +14,7 @@ use std::thread; // 2. Thread 2 blocks. // 3. Thread 3 unblocks both thread 1 and thread 2. // 4. Thread 1 reads. -// 5. Thread 2's `read` can neber complete -> deadlocked. +// 5. Thread 2's `read` can never complete -> deadlocked. fn main() { // eventfd write will block when EFD_NONBLOCK flag is clear -- cgit 1.4.1-3-g733a5 From 7dcba03d28ee69764e5a9492d1f1f2518e36834f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 22 Nov 2024 07:37:38 +0100 Subject: disable solaris on CI for now --- src/tools/miri/ci/ci.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/tools') diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index 0356d7ecf10..9b020d029a6 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -153,7 +153,7 @@ case $HOST_TARGET in TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe - TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe + # TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random sync threadname pthread TEST_TARGET=wasm32-wasip2 run_tests_minimal $BASIC wasm TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std empty_main wasm # this target doesn't really have std -- cgit 1.4.1-3-g733a5 From 004edb27cf319b3d844f3bce397aa1079235a390 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 22 Nov 2024 08:08:34 +0000 Subject: sysconf interception fix for solarish systems. also adding the `_SC_PAGESIZE` alias `_SC_PAGE_SIZE` supported by Linux, macOS and FreeBSD. close #4050 --- src/tools/miri/ci/ci.sh | 2 +- .../miri/src/shims/unix/android/foreign_items.rs | 9 ++++ src/tools/miri/src/shims/unix/foreign_items.rs | 58 +++++++++++----------- .../miri/src/shims/unix/freebsd/foreign_items.rs | 9 ++++ .../miri/src/shims/unix/linux/foreign_items.rs | 9 ++++ .../miri/src/shims/unix/macos/foreign_items.rs | 8 +++ .../miri/src/shims/unix/solarish/foreign_items.rs | 8 +++ src/tools/miri/tests/pass-dep/libc/libc-sysconf.rs | 17 +++++++ 8 files changed, 90 insertions(+), 30 deletions(-) create mode 100644 src/tools/miri/tests/pass-dep/libc/libc-sysconf.rs (limited to 'src/tools') diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index 9b020d029a6..0356d7ecf10 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -153,7 +153,7 @@ case $HOST_TARGET in TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe - # TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe + TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random sync threadname pthread TEST_TARGET=wasm32-wasip2 run_tests_minimal $BASIC wasm TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std empty_main wasm # this target doesn't really have std diff --git a/src/tools/miri/src/shims/unix/android/foreign_items.rs b/src/tools/miri/src/shims/unix/android/foreign_items.rs index 80ad40e1624..6c5a61437af 100644 --- a/src/tools/miri/src/shims/unix/android/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/android/foreign_items.rs @@ -2,6 +2,7 @@ use rustc_abi::ExternAbi; use rustc_span::Symbol; use crate::shims::unix::android::thread::prctl; +use crate::shims::unix::foreign_items::EvalContextExt as _; use crate::shims::unix::linux::syscall::syscall; use crate::*; @@ -20,6 +21,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); match link_name.as_str() { + // Querying system information + "sysconf" => { + let [val] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.sysconf(val)?; + this.write_scalar(result, dest)?; + } + // Miscellaneous "__errno" => { let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 55202a08149..a50ac1be77e 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -39,6 +39,35 @@ pub fn is_dyn_sym(name: &str, target_os: &str) -> bool { impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { + // Querying system information + fn sysconf(&mut self, val: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { + let this = self.eval_context_mut(); + + let name = this.read_scalar(val)?.to_i32()?; + // FIXME: Which of these are POSIX, and which are GNU/Linux? + // At least the names seem to all also exist on macOS. + let sysconfs: &[(&str, fn(&MiriInterpCx<'_>) -> Scalar)] = &[ + ("_SC_PAGESIZE", |this| Scalar::from_int(this.machine.page_size, this.pointer_size())), + ("_SC_PAGE_SIZE", |this| Scalar::from_int(this.machine.page_size, this.pointer_size())), + ("_SC_NPROCESSORS_CONF", |this| { + Scalar::from_int(this.machine.num_cpus, this.pointer_size()) + }), + ("_SC_NPROCESSORS_ONLN", |this| { + Scalar::from_int(this.machine.num_cpus, this.pointer_size()) + }), + // 512 seems to be a reasonable default. The value is not critical, in + // the sense that getpwuid_r takes and checks the buffer length. + ("_SC_GETPW_R_SIZE_MAX", |this| Scalar::from_int(512, this.pointer_size())), + ]; + for &(sysconf_name, value) in sysconfs { + let sysconf_name = this.eval_libc_i32(sysconf_name); + if sysconf_name == name { + return interp_ok(value(this)); + } + } + throw_unsup_format!("unimplemented sysconf name: {}", name) + } + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, @@ -393,35 +422,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } } - // Querying system information - "sysconf" => { - let [name] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - let name = this.read_scalar(name)?.to_i32()?; - // FIXME: Which of these are POSIX, and which are GNU/Linux? - // At least the names seem to all also exist on macOS. - let sysconfs: &[(&str, fn(&MiriInterpCx<'_>) -> Scalar)] = &[ - ("_SC_PAGESIZE", |this| Scalar::from_int(this.machine.page_size, this.pointer_size())), - ("_SC_NPROCESSORS_CONF", |this| Scalar::from_int(this.machine.num_cpus, this.pointer_size())), - ("_SC_NPROCESSORS_ONLN", |this| Scalar::from_int(this.machine.num_cpus, this.pointer_size())), - // 512 seems to be a reasonable default. The value is not critical, in - // the sense that getpwuid_r takes and checks the buffer length. - ("_SC_GETPW_R_SIZE_MAX", |this| Scalar::from_int(512, this.pointer_size())) - ]; - let mut result = None; - for &(sysconf_name, value) in sysconfs { - let sysconf_name = this.eval_libc_i32(sysconf_name); - if sysconf_name == name { - result = Some(value(this)); - break; - } - } - if let Some(result) = result { - this.write_scalar(result, dest)?; - } else { - throw_unsup_format!("unimplemented sysconf name: {}", name) - } - } - // Thread-local storage "pthread_key_create" => { let [key, dtor] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index 1346d8de7ea..ddea9ecc294 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -1,6 +1,7 @@ use rustc_abi::ExternAbi; use rustc_span::Symbol; +use crate::shims::unix::foreign_items::EvalContextExt as _; use crate::shims::unix::*; use crate::*; @@ -75,6 +76,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(result, dest)?; } + // Querying system information + "sysconf" => { + let [val] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.sysconf(val)?; + this.write_scalar(result, dest)?; + } + // Miscellaneous "__error" => { let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 85f0d6e1330..75b0afcac00 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -6,6 +6,7 @@ use self::shims::unix::linux::eventfd::EvalContextExt as _; use self::shims::unix::linux::mem::EvalContextExt as _; use self::shims::unix::linux::syscall::syscall; use crate::machine::{SIGRTMAX, SIGRTMIN}; +use crate::shims::unix::foreign_items::EvalContextExt as _; use crate::shims::unix::*; use crate::*; @@ -124,6 +125,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(result, dest)?; } + // Querying system information + "sysconf" => { + let [val] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.sysconf(val)?; + this.write_scalar(result, dest)?; + } + // Dynamically invoked syscalls "syscall" => { syscall(this, link_name, abi, args, dest)?; diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index 003025916cd..7f67a2cab36 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -2,6 +2,7 @@ use rustc_abi::ExternAbi; use rustc_span::Symbol; use super::sync::EvalContextExt as _; +use crate::shims::unix::foreign_items::EvalContextExt as _; use crate::shims::unix::*; use crate::*; @@ -167,6 +168,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(stack_size, dest)?; } + "sysconf" => { + let [val] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.sysconf(val)?; + this.write_scalar(result, dest)?; + } + // Threading "pthread_setname_np" => { let [name] = diff --git a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs index 526b64cff69..2eeab38e35c 100644 --- a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs @@ -1,6 +1,7 @@ use rustc_abi::ExternAbi; use rustc_span::Symbol; +use crate::shims::unix::foreign_items::EvalContextExt as _; use crate::shims::unix::*; use crate::*; @@ -112,6 +113,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_null(dest)?; } + "sysconf" | "__sysconf_xpg7" => { + let [val] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.sysconf(val)?; + this.write_scalar(result, dest)?; + } + _ => return interp_ok(EmulateItemResult::NotSupported), } interp_ok(EmulateItemResult::NeedsReturn) diff --git a/src/tools/miri/tests/pass-dep/libc/libc-sysconf.rs b/src/tools/miri/tests/pass-dep/libc/libc-sysconf.rs new file mode 100644 index 00000000000..34d5b1e38a6 --- /dev/null +++ b/src/tools/miri/tests/pass-dep/libc/libc-sysconf.rs @@ -0,0 +1,17 @@ +//@ignore-target: windows # Supported only on unixes + +fn test_sysconfbasic() { + unsafe { + let ncpus = libc::sysconf(libc::_SC_NPROCESSORS_CONF); + assert!(ncpus >= 1); + let psz = libc::sysconf(libc::_SC_PAGESIZE); + assert!(psz % 4096 == 0); + // note that in reality it can return -1 (no hard limit) on some platforms. + let gwmax = libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX); + assert!(gwmax >= 512); + } +} + +fn main() { + test_sysconfbasic(); +} -- cgit 1.4.1-3-g733a5 From bb55f5239a237f0b37973d49a357b4443446d5f0 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 23 Nov 2024 11:55:26 +0000 Subject: follow-up on #4052, making a miri evaluation context fn for strerror_r. --- .../miri/src/shims/unix/android/foreign_items.rs | 9 ---- src/tools/miri/src/shims/unix/foreign_items.rs | 54 ++++++++++++++++------ .../miri/src/shims/unix/freebsd/foreign_items.rs | 9 ---- .../miri/src/shims/unix/linux/foreign_items.rs | 14 +++--- .../miri/src/shims/unix/macos/foreign_items.rs | 8 ---- .../miri/src/shims/unix/solarish/foreign_items.rs | 2 +- .../miri/tests/pass-dep/libc/libc-strerror_r.rs | 16 +++++++ 7 files changed, 62 insertions(+), 50 deletions(-) create mode 100644 src/tools/miri/tests/pass-dep/libc/libc-strerror_r.rs (limited to 'src/tools') diff --git a/src/tools/miri/src/shims/unix/android/foreign_items.rs b/src/tools/miri/src/shims/unix/android/foreign_items.rs index 6c5a61437af..80ad40e1624 100644 --- a/src/tools/miri/src/shims/unix/android/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/android/foreign_items.rs @@ -2,7 +2,6 @@ use rustc_abi::ExternAbi; use rustc_span::Symbol; use crate::shims::unix::android::thread::prctl; -use crate::shims::unix::foreign_items::EvalContextExt as _; use crate::shims::unix::linux::syscall::syscall; use crate::*; @@ -21,14 +20,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); match link_name.as_str() { - // Querying system information - "sysconf" => { - let [val] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - let result = this.sysconf(val)?; - this.write_scalar(result, dest)?; - } - // Miscellaneous "__errno" => { let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index a50ac1be77e..5594bd4e790 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -68,6 +68,30 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { throw_unsup_format!("unimplemented sysconf name: {}", name) } + fn strerror_r( + &mut self, + errnum: &OpTy<'tcx>, + buf: &OpTy<'tcx>, + buflen: &OpTy<'tcx>, + ) -> InterpResult<'tcx, Scalar> { + let this = self.eval_context_mut(); + + let errnum = this.read_scalar(errnum)?; + let buf = this.read_pointer(buf)?; + let buflen = this.read_target_usize(buflen)?; + let error = this.try_errnum_to_io_error(errnum)?; + let formatted = match error { + Some(err) => format!("{err}"), + None => format!(""), + }; + let (complete, _) = this.write_os_str_to_c_str(OsStr::new(&formatted), buf, buflen)?; + if complete { + interp_ok(Scalar::from_i32(0)) + } else { + interp_ok(Scalar::from_i32(this.eval_libc_i32("ERANGE"))) + } + } + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, @@ -113,6 +137,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(result, dest)?; } + "sysconf" => { + let [val] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.sysconf(val)?; + this.write_scalar(result, dest)?; + } + // File descriptors "read" => { let [fd, buf, count] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; @@ -724,21 +755,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // We do not support forking, so there is nothing to do here. this.write_null(dest)?; } - "strerror_r" | "__xpg_strerror_r" => { - let [errnum, buf, buflen] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - let errnum = this.read_scalar(errnum)?; - let buf = this.read_pointer(buf)?; - let buflen = this.read_target_usize(buflen)?; - - let error = this.try_errnum_to_io_error(errnum)?; - let formatted = match error { - Some(err) => format!("{err}"), - None => format!(""), - }; - let (complete, _) = this.write_os_str_to_c_str(OsStr::new(&formatted), buf, buflen)?; - let ret = if complete { 0 } else { this.eval_libc_i32("ERANGE") }; - this.write_int(ret, dest)?; - } "getentropy" => { // This function is non-standard but exists with the same signature and behavior on // Linux, macOS, FreeBSD and Solaris/Illumos. @@ -766,6 +782,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_null(dest)?; } } + + "strerror_r" => { + let [errnum, buf, buflen] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.strerror_r(errnum, buf, buflen)?; + this.write_scalar(result, dest)?; + } + "getrandom" => { // This function is non-standard but exists with the same signature and behavior on // Linux, FreeBSD and Solaris/Illumos. diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index ddea9ecc294..1346d8de7ea 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -1,7 +1,6 @@ use rustc_abi::ExternAbi; use rustc_span::Symbol; -use crate::shims::unix::foreign_items::EvalContextExt as _; use crate::shims::unix::*; use crate::*; @@ -76,14 +75,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(result, dest)?; } - // Querying system information - "sysconf" => { - let [val] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - let result = this.sysconf(val)?; - this.write_scalar(result, dest)?; - } - // Miscellaneous "__error" => { let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 75b0afcac00..810e8d3340a 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -125,14 +125,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(result, dest)?; } - // Querying system information - "sysconf" => { - let [val] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - let result = this.sysconf(val)?; - this.write_scalar(result, dest)?; - } - // Dynamically invoked syscalls "syscall" => { syscall(this, link_name, abi, args, dest)?; @@ -152,6 +144,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let ptr = this.mremap(old_address, old_size, new_size, flags)?; this.write_scalar(ptr, dest)?; } + "__xpg_strerror_r" => { + let [errnum, buf, buflen] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.strerror_r(errnum, buf, buflen)?; + this.write_scalar(result, dest)?; + } "__errno_location" => { let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let errno_place = this.last_error_place()?; diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index 7f67a2cab36..003025916cd 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -2,7 +2,6 @@ use rustc_abi::ExternAbi; use rustc_span::Symbol; use super::sync::EvalContextExt as _; -use crate::shims::unix::foreign_items::EvalContextExt as _; use crate::shims::unix::*; use crate::*; @@ -168,13 +167,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(stack_size, dest)?; } - "sysconf" => { - let [val] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - let result = this.sysconf(val)?; - this.write_scalar(result, dest)?; - } - // Threading "pthread_setname_np" => { let [name] = diff --git a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs index 2eeab38e35c..1bbd25617e5 100644 --- a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs @@ -113,7 +113,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_null(dest)?; } - "sysconf" | "__sysconf_xpg7" => { + "__sysconf_xpg7" => { let [val] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let result = this.sysconf(val)?; diff --git a/src/tools/miri/tests/pass-dep/libc/libc-strerror_r.rs b/src/tools/miri/tests/pass-dep/libc/libc-strerror_r.rs new file mode 100644 index 00000000000..09885ce839d --- /dev/null +++ b/src/tools/miri/tests/pass-dep/libc/libc-strerror_r.rs @@ -0,0 +1,16 @@ +//@ignore-target: windows # Supported only on unixes + +fn main() { + unsafe { + let mut buf = vec![0u8; 32]; + assert_eq!(libc::strerror_r(libc::EPERM, buf.as_mut_ptr().cast(), buf.len()), 0); + let mut buf2 = vec![0u8; 64]; + assert_eq!(libc::strerror_r(-1i32, buf2.as_mut_ptr().cast(), buf2.len()), 0); + // This buffer is deliberately too small so this triggers ERANGE. + let mut buf3 = vec![0u8; 2]; + assert_eq!( + libc::strerror_r(libc::E2BIG, buf3.as_mut_ptr().cast(), buf3.len()), + libc::ERANGE + ); + } +} -- cgit 1.4.1-3-g733a5 From 1deb8f9ec1b8a08b76c5bf4ca8b63dd1702e644b Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 23 Nov 2024 09:53:45 +0000 Subject: sysconf: add _SC_OPEN_MAX --- src/tools/miri/src/shims/unix/foreign_items.rs | 5 +++++ src/tools/miri/tests/pass-dep/libc/libc-sysconf.rs | 2 ++ 2 files changed, 7 insertions(+) (limited to 'src/tools') diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 5594bd4e790..88ec32808b1 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -58,6 +58,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // 512 seems to be a reasonable default. The value is not critical, in // the sense that getpwuid_r takes and checks the buffer length. ("_SC_GETPW_R_SIZE_MAX", |this| Scalar::from_int(512, this.pointer_size())), + // Miri doesn't have a fixed limit on FDs, but we may be limited in terms of how + // many *host* FDs we can open. Just use some arbitrary, pretty big value; + // this can be adjusted if it causes problems. + // The spec imposes a minimum of `_POSIX_OPEN_MAX` (20). + ("_SC_OPEN_MAX", |this| Scalar::from_int(2_i32.pow(16), this.pointer_size())), ]; for &(sysconf_name, value) in sysconfs { let sysconf_name = this.eval_libc_i32(sysconf_name); diff --git a/src/tools/miri/tests/pass-dep/libc/libc-sysconf.rs b/src/tools/miri/tests/pass-dep/libc/libc-sysconf.rs index 34d5b1e38a6..b832b3033b7 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-sysconf.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-sysconf.rs @@ -9,6 +9,8 @@ fn test_sysconfbasic() { // note that in reality it can return -1 (no hard limit) on some platforms. let gwmax = libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX); assert!(gwmax >= 512); + let omax = libc::sysconf(libc::_SC_OPEN_MAX); + assert_eq!(omax, 65536); } } -- cgit 1.4.1-3-g733a5 From a3a29f50ef9f59ccd2e9178ff439d9825d79522f Mon Sep 17 00:00:00 2001 From: Max Niederman Date: Sun, 6 Oct 2024 23:09:30 -0700 Subject: cover guard patterns in rustfmt --- src/tools/rustfmt/src/patterns.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/tools') diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs index 6fe2d4a8520..7bc699b07b0 100644 --- a/src/tools/rustfmt/src/patterns.rs +++ b/src/tools/rustfmt/src/patterns.rs @@ -48,7 +48,8 @@ fn is_short_pattern_inner(pat: &ast::Pat) -> bool { | ast::PatKind::MacCall(..) | ast::PatKind::Slice(..) | ast::PatKind::Path(..) - | ast::PatKind::Range(..) => false, + | ast::PatKind::Range(..) + | ast::PatKind::Guard(..) => false, ast::PatKind::Tuple(ref subpats) => subpats.len() <= 1, ast::PatKind::TupleStruct(_, ref path, ref subpats) => { path.segments.len() <= 1 && subpats.len() <= 1 @@ -340,6 +341,7 @@ impl Rewrite for Pat { .map(|inner_pat| format!("({})", inner_pat)), PatKind::Err(_) => Err(RewriteError::Unknown), PatKind::Deref(_) => Err(RewriteError::Unknown), + PatKind::Guard(..) => Err(RewriteError::Unknown), } } } -- cgit 1.4.1-3-g733a5 From f86915a6828b64abfa75936ab0f1cddf7fdf7fee Mon Sep 17 00:00:00 2001 From: Max Niederman Date: Sat, 5 Oct 2024 22:09:20 -0700 Subject: cover guard patterns in clippy lints --- src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/tools') diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs index c7c837de505..c649d5e5e1e 100644 --- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs @@ -234,7 +234,7 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec>, focus_idx: us // In the case of only two patterns, replacement adds net characters. | Ref(_, Mutability::Not) // Dealt with elsewhere. - | Or(_) | Paren(_) | Deref(_) => false, + | Or(_) | Paren(_) | Deref(_) | Guard(..) => false, // Transform `box x | ... | box y` into `box (x | y)`. // // The cases below until `Slice(...)` deal with *singleton* products. -- cgit 1.4.1-3-g733a5 From 483f9e258055bcd37c162cbf2af24aa7450ab0ea Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 24 Nov 2024 22:57:33 +0100 Subject: Fix rustfmt according to review --- src/tools/rustfmt/src/patterns.rs | 4 ++-- src/tools/rustfmt/tests/target/guard_patterns.rs | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 src/tools/rustfmt/tests/target/guard_patterns.rs (limited to 'src/tools') diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs index 7bc699b07b0..7b4730eadc8 100644 --- a/src/tools/rustfmt/src/patterns.rs +++ b/src/tools/rustfmt/src/patterns.rs @@ -339,9 +339,9 @@ impl Rewrite for Pat { .max_width_error(shape.width, self.span)?, ) .map(|inner_pat| format!("({})", inner_pat)), - PatKind::Err(_) => Err(RewriteError::Unknown), + PatKind::Guard(..) => Ok(context.snippet(self.span).to_string()), PatKind::Deref(_) => Err(RewriteError::Unknown), - PatKind::Guard(..) => Err(RewriteError::Unknown), + PatKind::Err(_) => Err(RewriteError::Unknown), } } } diff --git a/src/tools/rustfmt/tests/target/guard_patterns.rs b/src/tools/rustfmt/tests/target/guard_patterns.rs new file mode 100644 index 00000000000..2e4667b916c --- /dev/null +++ b/src/tools/rustfmt/tests/target/guard_patterns.rs @@ -0,0 +1,12 @@ +#![feature(guard_patterns)] + +fn main() { + match user.subscription_plan() { + (Plan::Regular if user.credit() >= 100) | (Plan::Premium if user.credit() >= 80) => { + // Complete the transaction. + } + _ => { + // The user doesn't have enough credit, return an error message. + } + } +} -- cgit 1.4.1-3-g733a5 From 57c66159dae0e89930f75a0f60aa578bc7a86111 Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Wed, 6 Nov 2024 21:54:18 +0300 Subject: Added epoll and eventfd for Android --- src/tools/miri/ci/ci.sh | 2 +- .../miri/src/shims/unix/android/foreign_items.rs | 27 ++++++++++++++++++++++ src/tools/miri/src/shims/unix/linux/eventfd.rs | 3 --- .../tests/fail-dep/libc/libc-epoll-data-race.rs | 1 + .../tests/pass-dep/libc/libc-epoll-blocking.rs | 1 + .../tests/pass-dep/libc/libc-epoll-no-blocking.rs | 1 + src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs | 1 + 7 files changed, 32 insertions(+), 4 deletions(-) (limited to 'src/tools') diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index 0356d7ecf10..1e5a2847c6f 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -154,7 +154,7 @@ case $HOST_TARGET in TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe - TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random sync threadname pthread + TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random sync threadname pthread epoll eventfd TEST_TARGET=wasm32-wasip2 run_tests_minimal $BASIC wasm TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std empty_main wasm # this target doesn't really have std TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std diff --git a/src/tools/miri/src/shims/unix/android/foreign_items.rs b/src/tools/miri/src/shims/unix/android/foreign_items.rs index 80ad40e1624..4a005093b27 100644 --- a/src/tools/miri/src/shims/unix/android/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/android/foreign_items.rs @@ -1,6 +1,8 @@ use rustc_abi::ExternAbi; use rustc_span::Symbol; +use self::shims::unix::linux::epoll::EvalContextExt as _; +use self::shims::unix::linux::eventfd::EvalContextExt as _; use crate::shims::unix::android::thread::prctl; use crate::shims::unix::linux::syscall::syscall; use crate::*; @@ -20,6 +22,31 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); match link_name.as_str() { + // epoll, eventfd + "epoll_create1" => { + let [flag] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.epoll_create1(flag)?; + this.write_scalar(result, dest)?; + } + "epoll_ctl" => { + let [epfd, op, fd, event] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.epoll_ctl(epfd, op, fd, event)?; + this.write_scalar(result, dest)?; + } + "epoll_wait" => { + let [epfd, events, maxevents, timeout] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + this.epoll_wait(epfd, events, maxevents, timeout, dest)?; + } + "eventfd" => { + let [val, flag] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.eventfd(val, flag)?; + this.write_scalar(result, dest)?; + } + // Miscellaneous "__errno" => { let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; diff --git a/src/tools/miri/src/shims/unix/linux/eventfd.rs b/src/tools/miri/src/shims/unix/linux/eventfd.rs index 2ec3d792d94..6aee9c1d86b 100644 --- a/src/tools/miri/src/shims/unix/linux/eventfd.rs +++ b/src/tools/miri/src/shims/unix/linux/eventfd.rs @@ -144,9 +144,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn eventfd(&mut self, val: &OpTy<'tcx>, flags: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - // eventfd is Linux specific. - this.assert_target_os("linux", "eventfd"); - let val = this.read_scalar(val)?.to_u32()?; let mut flags = this.read_scalar(flags)?.to_i32()?; diff --git a/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs b/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs index 398bc92b392..0794867118c 100644 --- a/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs +++ b/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs @@ -3,6 +3,7 @@ //! and therefore still report a data race for things that need to see the second event //! to be considered synchronized. //@only-target: linux +//@only-target: android // ensure deterministic schedule //@compile-flags: -Zmiri-preemption-rate=0 diff --git a/src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs b/src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs index 9bcc776e281..d45dc5af489 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs @@ -1,4 +1,5 @@ //@only-target: linux +//@only-target: android // test_epoll_block_then_unblock and test_epoll_race depend on a deterministic schedule. //@compile-flags: -Zmiri-preemption-rate=0 diff --git a/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs b/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs index 288c1d41f30..59141cd5dcc 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs @@ -1,4 +1,5 @@ //@only-target: linux +//@only-target: android use std::convert::TryInto; diff --git a/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs b/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs index dd9c0eb0b54..767ab1065c2 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs @@ -1,4 +1,5 @@ //@only-target: linux +//@only-target: android // test_race, test_blocking_read and test_blocking_write depend on a deterministic schedule. //@compile-flags: -Zmiri-preemption-rate=0 -- cgit 1.4.1-3-g733a5 From 64f42a4107a6d095fd7ea4fb726f7a73ba235ada Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Mon, 11 Nov 2024 15:38:10 +0300 Subject: Fixed test target Co-authored-by: Ralf Jung --- src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/tools') diff --git a/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs b/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs index 0794867118c..7bef687e339 100644 --- a/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs +++ b/src/tools/miri/tests/fail-dep/libc/libc-epoll-data-race.rs @@ -2,8 +2,7 @@ //! and we only read one of them, we do not synchronize with the other events //! and therefore still report a data race for things that need to see the second event //! to be considered synchronized. -//@only-target: linux -//@only-target: android +//@only-target: linux android // ensure deterministic schedule //@compile-flags: -Zmiri-preemption-rate=0 -- cgit 1.4.1-3-g733a5 From 13aa5fbd7866a975a7f56b42aa111bb16dac4b1d Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Mon, 11 Nov 2024 18:20:26 +0300 Subject: Added linux_like module --- .../miri/src/shims/unix/android/foreign_items.rs | 6 +- src/tools/miri/src/shims/unix/fd.rs | 2 +- src/tools/miri/src/shims/unix/linux/epoll.rs | 663 --------------------- src/tools/miri/src/shims/unix/linux/eventfd.rs | 330 ---------- .../miri/src/shims/unix/linux/foreign_items.rs | 6 +- src/tools/miri/src/shims/unix/linux/mod.rs | 4 - src/tools/miri/src/shims/unix/linux/sync.rs | 223 ------- src/tools/miri/src/shims/unix/linux/syscall.rs | 63 -- src/tools/miri/src/shims/unix/linux_like/epoll.rs | 663 +++++++++++++++++++++ .../miri/src/shims/unix/linux_like/eventfd.rs | 330 ++++++++++ src/tools/miri/src/shims/unix/linux_like/mod.rs | 4 + src/tools/miri/src/shims/unix/linux_like/sync.rs | 223 +++++++ .../miri/src/shims/unix/linux_like/syscall.rs | 63 ++ src/tools/miri/src/shims/unix/mod.rs | 3 +- src/tools/miri/src/shims/unix/unnamed_socket.rs | 2 +- 15 files changed, 1293 insertions(+), 1292 deletions(-) delete mode 100644 src/tools/miri/src/shims/unix/linux/epoll.rs delete mode 100644 src/tools/miri/src/shims/unix/linux/eventfd.rs delete mode 100644 src/tools/miri/src/shims/unix/linux/sync.rs delete mode 100644 src/tools/miri/src/shims/unix/linux/syscall.rs create mode 100644 src/tools/miri/src/shims/unix/linux_like/epoll.rs create mode 100644 src/tools/miri/src/shims/unix/linux_like/eventfd.rs create mode 100644 src/tools/miri/src/shims/unix/linux_like/mod.rs create mode 100644 src/tools/miri/src/shims/unix/linux_like/sync.rs create mode 100644 src/tools/miri/src/shims/unix/linux_like/syscall.rs (limited to 'src/tools') diff --git a/src/tools/miri/src/shims/unix/android/foreign_items.rs b/src/tools/miri/src/shims/unix/android/foreign_items.rs index 4a005093b27..f9003885450 100644 --- a/src/tools/miri/src/shims/unix/android/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/android/foreign_items.rs @@ -1,10 +1,10 @@ use rustc_abi::ExternAbi; use rustc_span::Symbol; -use self::shims::unix::linux::epoll::EvalContextExt as _; -use self::shims::unix::linux::eventfd::EvalContextExt as _; use crate::shims::unix::android::thread::prctl; -use crate::shims::unix::linux::syscall::syscall; +use crate::shims::unix::linux_like::epoll::EvalContextExt as _; +use crate::shims::unix::linux_like::eventfd::EvalContextExt as _; +use crate::shims::unix::linux_like::syscall::syscall; use crate::*; pub fn is_dyn_sym(_name: &str) -> bool { diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs index 27bdd508f77..4e80630e674 100644 --- a/src/tools/miri/src/shims/unix/fd.rs +++ b/src/tools/miri/src/shims/unix/fd.rs @@ -10,7 +10,7 @@ use std::rc::{Rc, Weak}; use rustc_abi::Size; use crate::helpers::check_min_arg_count; -use crate::shims::unix::linux::epoll::EpollReadyEvents; +use crate::shims::unix::linux_like::epoll::EpollReadyEvents; use crate::shims::unix::*; use crate::*; diff --git a/src/tools/miri/src/shims/unix/linux/epoll.rs b/src/tools/miri/src/shims/unix/linux/epoll.rs deleted file mode 100644 index b20b12528db..00000000000 --- a/src/tools/miri/src/shims/unix/linux/epoll.rs +++ /dev/null @@ -1,663 +0,0 @@ -use std::cell::RefCell; -use std::collections::BTreeMap; -use std::io; -use std::rc::{Rc, Weak}; -use std::time::Duration; - -use crate::concurrency::VClock; -use crate::shims::unix::fd::{FdId, FileDescriptionRef, WeakFileDescriptionRef}; -use crate::shims::unix::*; -use crate::*; - -/// An `Epoll` file descriptor connects file handles and epoll events -#[derive(Clone, Debug, Default)] -struct Epoll { - /// A map of EpollEventInterests registered under this epoll instance. - /// Each entry is differentiated using FdId and file descriptor value. - interest_list: RefCell>>>, - /// A map of EpollEventInstance that will be returned when `epoll_wait` is called. - /// Similar to interest_list, the entry is also differentiated using FdId - /// and file descriptor value. - // This is an Rc because EpollInterest need to hold a reference to update - // it. - ready_list: Rc, - /// A list of thread ids blocked on this epoll instance. - thread_id: RefCell>, -} - -/// EpollEventInstance contains information that will be returned by epoll_wait. -#[derive(Debug)] -pub struct EpollEventInstance { - /// Xor-ed event types that happened to the file description. - events: u32, - /// Original data retrieved from `epoll_event` during `epoll_ctl`. - data: u64, - /// The release clock associated with this event. - clock: VClock, -} - -impl EpollEventInstance { - pub fn new(events: u32, data: u64) -> EpollEventInstance { - EpollEventInstance { events, data, clock: Default::default() } - } -} - -/// EpollEventInterest registers the file description information to an epoll -/// instance during a successful `epoll_ctl` call. It also stores additional -/// information needed to check and update readiness state for `epoll_wait`. -/// -/// `events` and `data` field matches the `epoll_event` struct defined -/// by the epoll_ctl man page. For more information -/// see the man page: -/// -/// -#[derive(Clone, Debug)] -pub struct EpollEventInterest { - /// The file descriptor value of the file description registered. - /// This is only used for ready_list, to inform userspace which FD triggered an event. - /// For that, it is crucial to preserve the original FD number. - /// This FD number must never be "dereferenced" to a file description inside Miri. - fd_num: i32, - /// The events bitmask retrieved from `epoll_event`. - events: u32, - /// The data retrieved from `epoll_event`. - /// libc's data field in epoll_event can store integer or pointer, - /// but only u64 is supported for now. - /// - data: u64, - /// Ready list of the epoll instance under which this EpollEventInterest is registered. - ready_list: Rc, - /// The epoll file description that this EpollEventInterest is registered under. - weak_epfd: WeakFileDescriptionRef, -} - -/// EpollReadyEvents reflects the readiness of a file description. -pub struct EpollReadyEvents { - /// The associated file is available for read(2) operations, in the sense that a read will not block. - /// (I.e., returning EOF is considered "ready".) - pub epollin: bool, - /// The associated file is available for write(2) operations, in the sense that a write will not block. - pub epollout: bool, - /// Stream socket peer closed connection, or shut down writing - /// half of connection. - pub epollrdhup: bool, - /// For stream socket, this event merely indicates that the peer - /// closed its end of the channel. - /// Unlike epollrdhup, this should only be set when the stream is fully closed. - /// epollrdhup also gets set when only the write half is closed, which is possible - /// via `shutdown(_, SHUT_WR)`. - pub epollhup: bool, - /// Error condition happened on the associated file descriptor. - pub epollerr: bool, -} - -#[derive(Debug, Default)] -struct ReadyList { - mapping: RefCell>, -} - -impl EpollReadyEvents { - pub fn new() -> Self { - EpollReadyEvents { - epollin: false, - epollout: false, - epollrdhup: false, - epollhup: false, - epollerr: false, - } - } - - pub fn get_event_bitmask<'tcx>(&self, ecx: &MiriInterpCx<'tcx>) -> u32 { - let epollin = ecx.eval_libc_u32("EPOLLIN"); - let epollout = ecx.eval_libc_u32("EPOLLOUT"); - let epollrdhup = ecx.eval_libc_u32("EPOLLRDHUP"); - let epollhup = ecx.eval_libc_u32("EPOLLHUP"); - let epollerr = ecx.eval_libc_u32("EPOLLERR"); - - let mut bitmask = 0; - if self.epollin { - bitmask |= epollin; - } - if self.epollout { - bitmask |= epollout; - } - if self.epollrdhup { - bitmask |= epollrdhup; - } - if self.epollhup { - bitmask |= epollhup; - } - if self.epollerr { - bitmask |= epollerr; - } - bitmask - } -} - -impl Epoll { - fn get_ready_list(&self) -> Rc { - Rc::clone(&self.ready_list) - } -} - -impl FileDescription for Epoll { - fn name(&self) -> &'static str { - "epoll" - } - - fn close<'tcx>( - self: Box, - _communicate_allowed: bool, - _ecx: &mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx, io::Result<()>> { - interp_ok(Ok(())) - } -} - -/// The table of all EpollEventInterest. -/// The BTreeMap key is the FdId of an active file description registered with -/// any epoll instance. The value is a list of EpollEventInterest associated -/// with that file description. -pub struct EpollInterestTable(BTreeMap>>>); - -impl EpollInterestTable { - pub(crate) fn new() -> Self { - EpollInterestTable(BTreeMap::new()) - } - - pub fn insert_epoll_interest(&mut self, id: FdId, fd: Weak>) { - match self.0.get_mut(&id) { - Some(fds) => { - fds.push(fd); - } - None => { - let vec = vec![fd]; - self.0.insert(id, vec); - } - } - } - - pub fn get_epoll_interest(&self, id: FdId) -> Option<&Vec>>> { - self.0.get(&id) - } - - pub fn get_epoll_interest_mut( - &mut self, - id: FdId, - ) -> Option<&mut Vec>>> { - self.0.get_mut(&id) - } - - pub fn remove(&mut self, id: FdId) { - self.0.remove(&id); - } -} - -impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} -pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { - /// This function returns a file descriptor referring to the new `Epoll` instance. This file - /// descriptor is used for all subsequent calls to the epoll interface. If the `flags` argument - /// is 0, then this function is the same as `epoll_create()`. - /// - /// - fn epoll_create1(&mut self, flags: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { - let this = self.eval_context_mut(); - - let flags = this.read_scalar(flags)?.to_i32()?; - - let epoll_cloexec = this.eval_libc_i32("EPOLL_CLOEXEC"); - - // Miri does not support exec, so EPOLL_CLOEXEC flag has no effect. - if flags != epoll_cloexec && flags != 0 { - throw_unsup_format!( - "epoll_create1: flag {:#x} is unsupported, only 0 or EPOLL_CLOEXEC are allowed", - flags - ); - } - - let fd = this.machine.fds.insert_new(Epoll::default()); - interp_ok(Scalar::from_i32(fd)) - } - - /// This function performs control operations on the `Epoll` instance referred to by the file - /// descriptor `epfd`. It requests that the operation `op` be performed for the target file - /// descriptor, `fd`. - /// - /// Valid values for the op argument are: - /// `EPOLL_CTL_ADD` - Register the target file descriptor `fd` on the `Epoll` instance referred - /// to by the file descriptor `epfd` and associate the event `event` with the internal file - /// linked to `fd`. - /// `EPOLL_CTL_MOD` - Change the event `event` associated with the target file descriptor `fd`. - /// `EPOLL_CTL_DEL` - Deregister the target file descriptor `fd` from the `Epoll` instance - /// referred to by `epfd`. The `event` is ignored and can be null. - /// - /// - fn epoll_ctl( - &mut self, - epfd: &OpTy<'tcx>, - op: &OpTy<'tcx>, - fd: &OpTy<'tcx>, - event: &OpTy<'tcx>, - ) -> InterpResult<'tcx, Scalar> { - let this = self.eval_context_mut(); - - let epfd_value = this.read_scalar(epfd)?.to_i32()?; - let op = this.read_scalar(op)?.to_i32()?; - let fd = this.read_scalar(fd)?.to_i32()?; - let event = this.deref_pointer_as(event, this.libc_ty_layout("epoll_event"))?; - - let epoll_ctl_add = this.eval_libc_i32("EPOLL_CTL_ADD"); - let epoll_ctl_mod = this.eval_libc_i32("EPOLL_CTL_MOD"); - let epoll_ctl_del = this.eval_libc_i32("EPOLL_CTL_DEL"); - let epollin = this.eval_libc_u32("EPOLLIN"); - let epollout = this.eval_libc_u32("EPOLLOUT"); - let epollrdhup = this.eval_libc_u32("EPOLLRDHUP"); - let epollet = this.eval_libc_u32("EPOLLET"); - let epollhup = this.eval_libc_u32("EPOLLHUP"); - let epollerr = this.eval_libc_u32("EPOLLERR"); - - // Throw EINVAL if epfd and fd have the same value. - if epfd_value == fd { - return this.set_last_error_and_return_i32(LibcError("EINVAL")); - } - - // Check if epfd is a valid epoll file descriptor. - let Some(epfd) = this.machine.fds.get(epfd_value) else { - return this.set_last_error_and_return_i32(LibcError("EBADF")); - }; - let epoll_file_description = epfd - .downcast::() - .ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_ctl`"))?; - - let mut interest_list = epoll_file_description.interest_list.borrow_mut(); - let ready_list = &epoll_file_description.ready_list; - - let Some(fd_ref) = this.machine.fds.get(fd) else { - return this.set_last_error_and_return_i32(LibcError("EBADF")); - }; - let id = fd_ref.get_id(); - - if op == epoll_ctl_add || op == epoll_ctl_mod { - // Read event bitmask and data from epoll_event passed by caller. - let mut events = this.read_scalar(&this.project_field(&event, 0)?)?.to_u32()?; - let data = this.read_scalar(&this.project_field(&event, 1)?)?.to_u64()?; - - // Unset the flag we support to discover if any unsupported flags are used. - let mut flags = events; - // epoll_wait(2) will always wait for epollhup and epollerr; it is not - // necessary to set it in events when calling epoll_ctl(). - // So we will always set these two event types. - events |= epollhup; - events |= epollerr; - - if events & epollet != epollet { - // We only support edge-triggered notification for now. - throw_unsup_format!("epoll_ctl: epollet flag must be included."); - } else { - flags &= !epollet; - } - if flags & epollin == epollin { - flags &= !epollin; - } - if flags & epollout == epollout { - flags &= !epollout; - } - if flags & epollrdhup == epollrdhup { - flags &= !epollrdhup; - } - if flags & epollhup == epollhup { - flags &= !epollhup; - } - if flags & epollerr == epollerr { - flags &= !epollerr; - } - if flags != 0 { - throw_unsup_format!( - "epoll_ctl: encountered unknown unsupported flags {:#x}", - flags - ); - } - - let epoll_key = (id, fd); - - // Check the existence of fd in the interest list. - if op == epoll_ctl_add { - if interest_list.contains_key(&epoll_key) { - return this.set_last_error_and_return_i32(LibcError("EEXIST")); - } - } else { - if !interest_list.contains_key(&epoll_key) { - return this.set_last_error_and_return_i32(LibcError("ENOENT")); - } - } - - // Create an epoll_interest. - let interest = Rc::new(RefCell::new(EpollEventInterest { - fd_num: fd, - events, - data, - ready_list: Rc::clone(ready_list), - weak_epfd: epfd.downgrade(), - })); - - if op == epoll_ctl_add { - // Insert an epoll_interest to global epoll_interest list. - this.machine.epoll_interests.insert_epoll_interest(id, Rc::downgrade(&interest)); - interest_list.insert(epoll_key, Rc::clone(&interest)); - } else { - // Directly modify the epoll_interest so the global epoll_event_interest table - // will be updated too. - let mut epoll_interest = interest_list.get_mut(&epoll_key).unwrap().borrow_mut(); - epoll_interest.events = events; - epoll_interest.data = data; - } - - // Notification will be returned for current epfd if there is event in the file - // descriptor we registered. - check_and_update_one_event_interest(&fd_ref, interest, id, this)?; - interp_ok(Scalar::from_i32(0)) - } else if op == epoll_ctl_del { - let epoll_key = (id, fd); - - // Remove epoll_event_interest from interest_list. - let Some(epoll_interest) = interest_list.remove(&epoll_key) else { - return this.set_last_error_and_return_i32(LibcError("ENOENT")); - }; - // All related Weak will fail to upgrade after the drop. - drop(epoll_interest); - - // Remove related epoll_interest from ready list. - ready_list.mapping.borrow_mut().remove(&epoll_key); - - // Remove dangling EpollEventInterest from its global table. - // .unwrap() below should succeed because the file description id must have registered - // at least one epoll_interest, if not, it will fail when removing epoll_interest from - // interest list. - this.machine - .epoll_interests - .get_epoll_interest_mut(id) - .unwrap() - .retain(|event| event.upgrade().is_some()); - - interp_ok(Scalar::from_i32(0)) - } else { - throw_unsup_format!("unsupported epoll_ctl operation: {op}"); - } - } - - /// The `epoll_wait()` system call waits for events on the `Epoll` - /// instance referred to by the file descriptor `epfd`. The buffer - /// pointed to by `events` is used to return information from the ready - /// list about file descriptors in the interest list that have some - /// events available. Up to `maxevents` are returned by `epoll_wait()`. - /// The `maxevents` argument must be greater than zero. - /// - /// The `timeout` argument specifies the number of milliseconds that - /// `epoll_wait()` will block. Time is measured against the - /// CLOCK_MONOTONIC clock. If the timeout is zero, the function will not block, - /// while if the timeout is -1, the function will block - /// until at least one event has been retrieved (or an error - /// occurred). - /// - /// A call to `epoll_wait()` will block until either: - /// • a file descriptor delivers an event; - /// • the call is interrupted by a signal handler; or - /// • the timeout expires. - /// - /// Note that the timeout interval will be rounded up to the system - /// clock granularity, and kernel scheduling delays mean that the - /// blocking interval may overrun by a small amount. Specifying a - /// timeout of -1 causes `epoll_wait()` to block indefinitely, while - /// specifying a timeout equal to zero cause `epoll_wait()` to return - /// immediately, even if no events are available. - /// - /// On success, `epoll_wait()` returns the number of file descriptors - /// ready for the requested I/O, or zero if no file descriptor became - /// ready during the requested timeout milliseconds. On failure, - /// `epoll_wait()` returns -1 and errno is set to indicate the error. - /// - /// - fn epoll_wait( - &mut self, - epfd: &OpTy<'tcx>, - events_op: &OpTy<'tcx>, - maxevents: &OpTy<'tcx>, - timeout: &OpTy<'tcx>, - dest: &MPlaceTy<'tcx>, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - - let epfd_value = this.read_scalar(epfd)?.to_i32()?; - let events = this.read_immediate(events_op)?; - let maxevents = this.read_scalar(maxevents)?.to_i32()?; - let timeout = this.read_scalar(timeout)?.to_i32()?; - - if epfd_value <= 0 || maxevents <= 0 { - return this.set_last_error_and_return(LibcError("EINVAL"), dest); - } - - // This needs to come after the maxevents value check, or else maxevents.try_into().unwrap() - // will fail. - let event = this.deref_pointer_as( - &events, - this.libc_array_ty_layout("epoll_event", maxevents.try_into().unwrap()), - )?; - - let Some(epfd) = this.machine.fds.get(epfd_value) else { - return this.set_last_error_and_return(LibcError("EBADF"), dest); - }; - // Create a weak ref of epfd and pass it to callback so we will make sure that epfd - // is not close after the thread unblocks. - let weak_epfd = epfd.downgrade(); - - // We just need to know if the ready list is empty and borrow the thread_ids out. - // The whole logic is wrapped inside a block so we don't need to manually drop epfd later. - let ready_list_empty; - let mut thread_ids; - { - let epoll_file_description = epfd - .downcast::() - .ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_wait`"))?; - ready_list_empty = epoll_file_description.ready_list.mapping.borrow().is_empty(); - thread_ids = epoll_file_description.thread_id.borrow_mut(); - } - if timeout == 0 || !ready_list_empty { - // If the ready list is not empty, or the timeout is 0, we can return immediately. - return_ready_list(epfd_value, weak_epfd, dest, &event, this)?; - } else { - // Blocking - let timeout = match timeout { - 0.. => { - let duration = Duration::from_millis(timeout.try_into().unwrap()); - Some((TimeoutClock::Monotonic, TimeoutAnchor::Relative, duration)) - } - -1 => None, - ..-1 => { - throw_unsup_format!( - "epoll_wait: Only timeout values greater than or equal to -1 are supported." - ); - } - }; - thread_ids.push(this.active_thread()); - let dest = dest.clone(); - this.block_thread( - BlockReason::Epoll, - timeout, - callback!( - @capture<'tcx> { - epfd_value: i32, - weak_epfd: WeakFileDescriptionRef, - dest: MPlaceTy<'tcx>, - event: MPlaceTy<'tcx>, - } - @unblock = |this| { - return_ready_list(epfd_value, weak_epfd, &dest, &event, this)?; - interp_ok(()) - } - @timeout = |this| { - // No notification after blocking timeout. - let Some(epfd) = weak_epfd.upgrade() else { - throw_unsup_format!("epoll FD {epfd_value} got closed while blocking.") - }; - // Remove the current active thread_id from the blocked thread_id list. - epfd.downcast::() - .ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_wait`"))? - .thread_id.borrow_mut() - .retain(|&id| id != this.active_thread()); - this.write_int(0, &dest)?; - interp_ok(()) - } - ), - ); - } - interp_ok(()) - } - - /// For a specific file description, get its ready events and update the corresponding ready - /// list. This function should be called whenever an event causes more bytes or an EOF to become - /// newly readable from an FD, and whenever more bytes can be written to an FD or no more future - /// writes are possible. - /// - /// This *will* report an event if anyone is subscribed to it, without any further filtering, so - /// do not call this function when an FD didn't have anything happen to it! - fn check_and_update_readiness( - &mut self, - fd_ref: &FileDescriptionRef, - ) -> InterpResult<'tcx, ()> { - let this = self.eval_context_mut(); - let id = fd_ref.get_id(); - let mut waiter = Vec::new(); - // Get a list of EpollEventInterest that is associated to a specific file description. - if let Some(epoll_interests) = this.machine.epoll_interests.get_epoll_interest(id) { - for weak_epoll_interest in epoll_interests { - if let Some(epoll_interest) = weak_epoll_interest.upgrade() { - let is_updated = check_and_update_one_event_interest( - fd_ref, - epoll_interest.clone(), - id, - this, - )?; - if is_updated { - // Edge-triggered notification only notify one thread even if there are - // multiple threads blocked on the same epfd. - - // This unwrap can never fail because if the current epoll instance were - // closed, the upgrade of weak_epoll_interest - // above would fail. This guarantee holds because only the epoll instance - // holds a strong ref to epoll_interest. - let epfd = epoll_interest.borrow().weak_epfd.upgrade().unwrap(); - // FIXME: We can randomly pick a thread to unblock. - - let epoll = epfd.downcast::().unwrap(); - - if let Some(thread_id) = epoll.thread_id.borrow_mut().pop() { - waiter.push(thread_id); - }; - } - } - } - } - waiter.sort(); - waiter.dedup(); - for thread_id in waiter { - this.unblock_thread(thread_id, BlockReason::Epoll)?; - } - interp_ok(()) - } -} - -/// This function takes in ready list and returns EpollEventInstance with file description -/// that is not closed. -fn ready_list_next( - ecx: &MiriInterpCx<'_>, - ready_list: &mut BTreeMap<(FdId, i32), EpollEventInstance>, -) -> Option { - while let Some((epoll_key, epoll_event_instance)) = ready_list.pop_first() { - // This ensures that we only return events that we are interested. The FD might have been closed since - // the event was generated, in which case we are not interested anymore. - // When a file description is fully closed, it gets removed from `machine.epoll_interests`, - // so we skip events whose FD is not in that map anymore. - if ecx.machine.epoll_interests.get_epoll_interest(epoll_key.0).is_some() { - return Some(epoll_event_instance); - } - } - None -} - -/// This helper function checks whether an epoll notification should be triggered for a specific -/// epoll_interest and, if necessary, triggers the notification, and returns whether the -/// notification was added/updated. Unlike check_and_update_readiness, this function sends a -/// notification to only one epoll instance. -fn check_and_update_one_event_interest<'tcx>( - fd_ref: &FileDescriptionRef, - interest: Rc>, - id: FdId, - ecx: &MiriInterpCx<'tcx>, -) -> InterpResult<'tcx, bool> { - // Get the bitmask of ready events for a file description. - let ready_events_bitmask = fd_ref.get_epoll_ready_events()?.get_event_bitmask(ecx); - let epoll_event_interest = interest.borrow(); - // This checks if any of the events specified in epoll_event_interest.events - // match those in ready_events. - let flags = epoll_event_interest.events & ready_events_bitmask; - // If there is any event that we are interested in being specified as ready, - // insert an epoll_return to the ready list. - if flags != 0 { - let epoll_key = (id, epoll_event_interest.fd_num); - let ready_list = &mut epoll_event_interest.ready_list.mapping.borrow_mut(); - let mut event_instance = EpollEventInstance::new(flags, epoll_event_interest.data); - // If we are tracking data races, remember the current clock so we can sync with it later. - ecx.release_clock(|clock| { - event_instance.clock.clone_from(clock); - }); - // Triggers the notification by inserting it to the ready list. - ready_list.insert(epoll_key, event_instance); - interp_ok(true) - } else { - interp_ok(false) - } -} - -/// Stores the ready list of the `epfd` epoll instance into `events` (which must be an array), -/// and the number of returned events into `dest`. -fn return_ready_list<'tcx>( - epfd_value: i32, - weak_epfd: WeakFileDescriptionRef, - dest: &MPlaceTy<'tcx>, - events: &MPlaceTy<'tcx>, - ecx: &mut MiriInterpCx<'tcx>, -) -> InterpResult<'tcx> { - let Some(epfd) = weak_epfd.upgrade() else { - throw_unsup_format!("epoll FD {epfd_value} got closed while blocking.") - }; - - let epoll_file_description = epfd - .downcast::() - .ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_wait`"))?; - - let ready_list = epoll_file_description.get_ready_list(); - - let mut ready_list = ready_list.mapping.borrow_mut(); - let mut num_of_events: i32 = 0; - let mut array_iter = ecx.project_array_fields(events)?; - - while let Some(des) = array_iter.next(ecx)? { - if let Some(epoll_event_instance) = ready_list_next(ecx, &mut ready_list) { - ecx.write_int_fields_named( - &[ - ("events", epoll_event_instance.events.into()), - ("u64", epoll_event_instance.data.into()), - ], - &des.1, - )?; - // Synchronize waking thread with the event of interest. - ecx.acquire_clock(&epoll_event_instance.clock); - - num_of_events = num_of_events.strict_add(1); - } else { - break; - } - } - ecx.write_int(num_of_events, dest)?; - interp_ok(()) -} diff --git a/src/tools/miri/src/shims/unix/linux/eventfd.rs b/src/tools/miri/src/shims/unix/linux/eventfd.rs deleted file mode 100644 index 6aee9c1d86b..00000000000 --- a/src/tools/miri/src/shims/unix/linux/eventfd.rs +++ /dev/null @@ -1,330 +0,0 @@ -//! Linux `eventfd` implementation. -use std::cell::{Cell, RefCell}; -use std::io; -use std::io::ErrorKind; - -use crate::concurrency::VClock; -use crate::shims::unix::fd::{FileDescriptionRef, WeakFileDescriptionRef}; -use crate::shims::unix::linux::epoll::{EpollReadyEvents, EvalContextExt as _}; -use crate::shims::unix::*; -use crate::*; - -/// Maximum value that the eventfd counter can hold. -const MAX_COUNTER: u64 = u64::MAX - 1; - -/// A kind of file descriptor created by `eventfd`. -/// The `Event` type isn't currently written to by `eventfd`. -/// The interface is meant to keep track of objects associated -/// with a file descriptor. For more information see the man -/// page below: -/// -/// -#[derive(Debug)] -struct Event { - /// The object contains an unsigned 64-bit integer (uint64_t) counter that is maintained by the - /// kernel. This counter is initialized with the value specified in the argument initval. - counter: Cell, - is_nonblock: bool, - clock: RefCell, - /// A list of thread ids blocked on eventfd::read. - blocked_read_tid: RefCell>, - /// A list of thread ids blocked on eventfd::write. - blocked_write_tid: RefCell>, -} - -impl FileDescription for Event { - fn name(&self) -> &'static str { - "event" - } - - fn get_epoll_ready_events<'tcx>(&self) -> InterpResult<'tcx, EpollReadyEvents> { - // We only check the status of EPOLLIN and EPOLLOUT flags for eventfd. If other event flags - // need to be supported in the future, the check should be added here. - - interp_ok(EpollReadyEvents { - epollin: self.counter.get() != 0, - epollout: self.counter.get() != MAX_COUNTER, - ..EpollReadyEvents::new() - }) - } - - fn close<'tcx>( - self: Box, - _communicate_allowed: bool, - _ecx: &mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx, io::Result<()>> { - interp_ok(Ok(())) - } - - /// Read the counter in the buffer and return the counter if succeeded. - fn read<'tcx>( - &self, - self_ref: &FileDescriptionRef, - _communicate_allowed: bool, - ptr: Pointer, - len: usize, - dest: &MPlaceTy<'tcx>, - ecx: &mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx> { - // We're treating the buffer as a `u64`. - let ty = ecx.machine.layouts.u64; - // Check the size of slice, and return error only if the size of the slice < 8. - if len < ty.size.bytes_usize() { - return ecx.set_last_error_and_return(ErrorKind::InvalidInput, dest); - } - - // eventfd read at the size of u64. - let buf_place = ecx.ptr_to_mplace_unaligned(ptr, ty); - - let weak_eventfd = self_ref.downgrade(); - eventfd_read(buf_place, dest, weak_eventfd, ecx) - } - - /// A write call adds the 8-byte integer value supplied in - /// its buffer (in native endianness) to the counter. The maximum value that may be - /// stored in the counter is the largest unsigned 64-bit value - /// minus 1 (i.e., 0xfffffffffffffffe). If the addition would - /// cause the counter's value to exceed the maximum, then the - /// write either blocks until a read is performed on the - /// file descriptor, or fails with the error EAGAIN if the - /// file descriptor has been made nonblocking. - /// - /// A write fails with the error EINVAL if the size of the - /// supplied buffer is less than 8 bytes, or if an attempt is - /// made to write the value 0xffffffffffffffff. - fn write<'tcx>( - &self, - self_ref: &FileDescriptionRef, - _communicate_allowed: bool, - ptr: Pointer, - len: usize, - dest: &MPlaceTy<'tcx>, - ecx: &mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx> { - // We're treating the buffer as a `u64`. - let ty = ecx.machine.layouts.u64; - // Check the size of slice, and return error only if the size of the slice < 8. - if len < ty.layout.size.bytes_usize() { - return ecx.set_last_error_and_return(ErrorKind::InvalidInput, dest); - } - - // Read the user-supplied value from the pointer. - let buf_place = ecx.ptr_to_mplace_unaligned(ptr, ty); - let num = ecx.read_scalar(&buf_place)?.to_u64()?; - - // u64::MAX as input is invalid because the maximum value of counter is u64::MAX - 1. - if num == u64::MAX { - return ecx.set_last_error_and_return(ErrorKind::InvalidInput, dest); - } - // If the addition does not let the counter to exceed the maximum value, update the counter. - // Else, block. - let weak_eventfd = self_ref.downgrade(); - eventfd_write(num, buf_place, dest, weak_eventfd, ecx) - } -} - -impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} -pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { - /// This function creates an `Event` that is used as an event wait/notify mechanism by - /// user-space applications, and by the kernel to notify user-space applications of events. - /// The `Event` contains an `u64` counter maintained by the kernel. The counter is initialized - /// with the value specified in the `initval` argument. - /// - /// A new file descriptor referring to the `Event` is returned. The `read`, `write`, `poll`, - /// `select`, and `close` operations can be performed on the file descriptor. For more - /// information on these operations, see the man page linked below. - /// - /// The `flags` are not currently implemented for eventfd. - /// The `flags` may be bitwise ORed to change the behavior of `eventfd`: - /// `EFD_CLOEXEC` - Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor. - /// `EFD_NONBLOCK` - Set the `O_NONBLOCK` file status flag on the new open file description. - /// `EFD_SEMAPHORE` - miri does not support semaphore-like semantics. - /// - /// - fn eventfd(&mut self, val: &OpTy<'tcx>, flags: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { - let this = self.eval_context_mut(); - - let val = this.read_scalar(val)?.to_u32()?; - let mut flags = this.read_scalar(flags)?.to_i32()?; - - let efd_cloexec = this.eval_libc_i32("EFD_CLOEXEC"); - let efd_nonblock = this.eval_libc_i32("EFD_NONBLOCK"); - let efd_semaphore = this.eval_libc_i32("EFD_SEMAPHORE"); - - if flags & efd_semaphore == efd_semaphore { - throw_unsup_format!("eventfd: EFD_SEMAPHORE is unsupported"); - } - - let mut is_nonblock = false; - // Unset the flag that we support. - // After unloading, flags != 0 means other flags are used. - if flags & efd_cloexec == efd_cloexec { - // cloexec is ignored because Miri does not support exec. - flags &= !efd_cloexec; - } - if flags & efd_nonblock == efd_nonblock { - flags &= !efd_nonblock; - is_nonblock = true; - } - if flags != 0 { - throw_unsup_format!("eventfd: encountered unknown unsupported flags {:#x}", flags); - } - - let fds = &mut this.machine.fds; - - let fd_value = fds.insert_new(Event { - counter: Cell::new(val.into()), - is_nonblock, - clock: RefCell::new(VClock::default()), - blocked_read_tid: RefCell::new(Vec::new()), - blocked_write_tid: RefCell::new(Vec::new()), - }); - - interp_ok(Scalar::from_i32(fd_value)) - } -} - -/// Block thread if the value addition will exceed u64::MAX -1, -/// else just add the user-supplied value to current counter. -fn eventfd_write<'tcx>( - num: u64, - buf_place: MPlaceTy<'tcx>, - dest: &MPlaceTy<'tcx>, - weak_eventfd: WeakFileDescriptionRef, - ecx: &mut MiriInterpCx<'tcx>, -) -> InterpResult<'tcx> { - let Some(eventfd_ref) = weak_eventfd.upgrade() else { - throw_unsup_format!("eventfd FD got closed while blocking.") - }; - - // Since we pass the weak file description ref, it is guaranteed to be - // an eventfd file description. - let eventfd = eventfd_ref.downcast::().unwrap(); - - match eventfd.counter.get().checked_add(num) { - Some(new_count @ 0..=MAX_COUNTER) => { - // Future `read` calls will synchronize with this write, so update the FD clock. - ecx.release_clock(|clock| { - eventfd.clock.borrow_mut().join(clock); - }); - - // Store new counter value. - eventfd.counter.set(new_count); - - // The state changed; we check and update the status of all supported event - // types for current file description. - ecx.check_and_update_readiness(&eventfd_ref)?; - - // Unblock *all* threads previously blocked on `read`. - // We need to take out the blocked thread ids and unblock them together, - // because `unblock_threads` may block them again and end up re-adding the - // thread to the blocked list. - let waiting_threads = std::mem::take(&mut *eventfd.blocked_read_tid.borrow_mut()); - // FIXME: We can randomize the order of unblocking. - for thread_id in waiting_threads { - ecx.unblock_thread(thread_id, BlockReason::Eventfd)?; - } - - // Return how many bytes we consumed from the user-provided buffer. - return ecx.write_int(buf_place.layout.size.bytes(), dest); - } - None | Some(u64::MAX) => { - // We can't update the state, so we have to block. - if eventfd.is_nonblock { - return ecx.set_last_error_and_return(ErrorKind::WouldBlock, dest); - } - - let dest = dest.clone(); - - eventfd.blocked_write_tid.borrow_mut().push(ecx.active_thread()); - - ecx.block_thread( - BlockReason::Eventfd, - None, - callback!( - @capture<'tcx> { - num: u64, - buf_place: MPlaceTy<'tcx>, - dest: MPlaceTy<'tcx>, - weak_eventfd: WeakFileDescriptionRef, - } - @unblock = |this| { - // When we get unblocked, try again. - eventfd_write(num, buf_place, &dest, weak_eventfd, this) - } - ), - ); - } - }; - interp_ok(()) -} - -/// Block thread if the current counter is 0, -/// else just return the current counter value to the caller and set the counter to 0. -fn eventfd_read<'tcx>( - buf_place: MPlaceTy<'tcx>, - dest: &MPlaceTy<'tcx>, - weak_eventfd: WeakFileDescriptionRef, - ecx: &mut MiriInterpCx<'tcx>, -) -> InterpResult<'tcx> { - let Some(eventfd_ref) = weak_eventfd.upgrade() else { - throw_unsup_format!("eventfd FD got closed while blocking.") - }; - - // Since we pass the weak file description ref to the callback function, it is guaranteed to be - // an eventfd file description. - let eventfd = eventfd_ref.downcast::().unwrap(); - - // Set counter to 0, get old value. - let counter = eventfd.counter.replace(0); - - // Block when counter == 0. - if counter == 0 { - if eventfd.is_nonblock { - return ecx.set_last_error_and_return(ErrorKind::WouldBlock, dest); - } - let dest = dest.clone(); - - eventfd.blocked_read_tid.borrow_mut().push(ecx.active_thread()); - - ecx.block_thread( - BlockReason::Eventfd, - None, - callback!( - @capture<'tcx> { - buf_place: MPlaceTy<'tcx>, - dest: MPlaceTy<'tcx>, - weak_eventfd: WeakFileDescriptionRef, - } - @unblock = |this| { - // When we get unblocked, try again. - eventfd_read(buf_place, &dest, weak_eventfd, this) - } - ), - ); - } else { - // Synchronize with all prior `write` calls to this FD. - ecx.acquire_clock(&eventfd.clock.borrow()); - - // Return old counter value into user-space buffer. - ecx.write_int(counter, &buf_place)?; - - // The state changed; we check and update the status of all supported event - // types for current file description. - ecx.check_and_update_readiness(&eventfd_ref)?; - - // Unblock *all* threads previously blocked on `write`. - // We need to take out the blocked thread ids and unblock them together, - // because `unblock_threads` may block them again and end up re-adding the - // thread to the blocked list. - let waiting_threads = std::mem::take(&mut *eventfd.blocked_write_tid.borrow_mut()); - // FIXME: We can randomize the order of unblocking. - for thread_id in waiting_threads { - ecx.unblock_thread(thread_id, BlockReason::Eventfd)?; - } - - // Tell userspace how many bytes we put into the buffer. - return ecx.write_int(buf_place.layout.size.bytes(), dest); - } - interp_ok(()) -} diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 810e8d3340a..bc3619090c0 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -1,10 +1,10 @@ use rustc_abi::ExternAbi; use rustc_span::Symbol; -use self::shims::unix::linux::epoll::EvalContextExt as _; -use self::shims::unix::linux::eventfd::EvalContextExt as _; use self::shims::unix::linux::mem::EvalContextExt as _; -use self::shims::unix::linux::syscall::syscall; +use self::shims::unix::linux_like::epoll::EvalContextExt as _; +use self::shims::unix::linux_like::eventfd::EvalContextExt as _; +use self::shims::unix::linux_like::syscall::syscall; use crate::machine::{SIGRTMAX, SIGRTMIN}; use crate::shims::unix::foreign_items::EvalContextExt as _; use crate::shims::unix::*; diff --git a/src/tools/miri/src/shims/unix/linux/mod.rs b/src/tools/miri/src/shims/unix/linux/mod.rs index 159e5aca031..c10dc52cb28 100644 --- a/src/tools/miri/src/shims/unix/linux/mod.rs +++ b/src/tools/miri/src/shims/unix/linux/mod.rs @@ -1,6 +1,2 @@ -pub mod epoll; -pub mod eventfd; pub mod foreign_items; pub mod mem; -pub mod sync; -pub mod syscall; diff --git a/src/tools/miri/src/shims/unix/linux/sync.rs b/src/tools/miri/src/shims/unix/linux/sync.rs deleted file mode 100644 index 51124fb2a00..00000000000 --- a/src/tools/miri/src/shims/unix/linux/sync.rs +++ /dev/null @@ -1,223 +0,0 @@ -use crate::concurrency::sync::FutexRef; -use crate::helpers::check_min_arg_count; -use crate::*; - -struct LinuxFutex { - futex: FutexRef, -} - -/// Implementation of the SYS_futex syscall. -/// `args` is the arguments *including* the syscall number. -pub fn futex<'tcx>( - ecx: &mut MiriInterpCx<'tcx>, - args: &[OpTy<'tcx>], - dest: &MPlaceTy<'tcx>, -) -> InterpResult<'tcx> { - // The amount of arguments used depends on the type of futex operation. - // The full futex syscall takes six arguments (excluding the syscall - // number), which is also the maximum amount of arguments a linux syscall - // can take on most architectures. - // However, not all futex operations use all six arguments. The unused ones - // may or may not be left out from the `syscall()` call. - // Therefore we don't use `check_arg_count` here, but only check for the - // number of arguments to fall within a range. - let [_, addr, op, val] = check_min_arg_count("`syscall(SYS_futex, ...)`", args)?; - - // The first three arguments (after the syscall number itself) are the same to all futex operations: - // (int *addr, int op, int val). - // We checked above that these definitely exist. - let addr = ecx.read_pointer(addr)?; - let op = ecx.read_scalar(op)?.to_i32()?; - let val = ecx.read_scalar(val)?.to_i32()?; - - // This is a vararg function so we have to bring our own type for this pointer. - let addr = ecx.ptr_to_mplace(addr, ecx.machine.layouts.i32); - - let futex_private = ecx.eval_libc_i32("FUTEX_PRIVATE_FLAG"); - let futex_wait = ecx.eval_libc_i32("FUTEX_WAIT"); - let futex_wait_bitset = ecx.eval_libc_i32("FUTEX_WAIT_BITSET"); - let futex_wake = ecx.eval_libc_i32("FUTEX_WAKE"); - let futex_wake_bitset = ecx.eval_libc_i32("FUTEX_WAKE_BITSET"); - let futex_realtime = ecx.eval_libc_i32("FUTEX_CLOCK_REALTIME"); - - // FUTEX_PRIVATE enables an optimization that stops it from working across processes. - // Miri doesn't support that anyway, so we ignore that flag. - match op & !futex_private { - // FUTEX_WAIT: (int *addr, int op = FUTEX_WAIT, int val, const timespec *timeout) - // Blocks the thread if *addr still equals val. Wakes up when FUTEX_WAKE is called on the same address, - // or *timeout expires. `timeout == null` for an infinite timeout. - // - // FUTEX_WAIT_BITSET: (int *addr, int op = FUTEX_WAIT_BITSET, int val, const timespec *timeout, int *_ignored, unsigned int bitset) - // This is identical to FUTEX_WAIT, except: - // - The timeout is absolute rather than relative. - // - You can specify the bitset to selecting what WAKE operations to respond to. - op if op & !futex_realtime == futex_wait || op & !futex_realtime == futex_wait_bitset => { - let wait_bitset = op & !futex_realtime == futex_wait_bitset; - - let (timeout, bitset) = if wait_bitset { - let [_, _, _, _, timeout, uaddr2, bitset] = - check_min_arg_count("`syscall(SYS_futex, FUTEX_WAIT_BITSET, ...)`", args)?; - let _timeout = ecx.read_pointer(timeout)?; - let _uaddr2 = ecx.read_pointer(uaddr2)?; - (timeout, ecx.read_scalar(bitset)?.to_u32()?) - } else { - let [_, _, _, _, timeout] = - check_min_arg_count("`syscall(SYS_futex, FUTEX_WAIT, ...)`", args)?; - (timeout, u32::MAX) - }; - - if bitset == 0 { - return ecx.set_last_error_and_return(LibcError("EINVAL"), dest); - } - - let timeout = ecx.deref_pointer_as(timeout, ecx.libc_ty_layout("timespec"))?; - let timeout = if ecx.ptr_is_null(timeout.ptr())? { - None - } else { - let duration = match ecx.read_timespec(&timeout)? { - Some(duration) => duration, - None => { - return ecx.set_last_error_and_return(LibcError("EINVAL"), dest); - } - }; - let timeout_clock = if op & futex_realtime == futex_realtime { - ecx.check_no_isolation( - "`futex` syscall with `op=FUTEX_WAIT` and non-null timeout with `FUTEX_CLOCK_REALTIME`", - )?; - TimeoutClock::RealTime - } else { - TimeoutClock::Monotonic - }; - let timeout_anchor = if wait_bitset { - // FUTEX_WAIT_BITSET uses an absolute timestamp. - TimeoutAnchor::Absolute - } else { - // FUTEX_WAIT uses a relative timestamp. - TimeoutAnchor::Relative - }; - Some((timeout_clock, timeout_anchor, duration)) - }; - // There may be a concurrent thread changing the value of addr - // and then invoking the FUTEX_WAKE syscall. It is critical that the - // effects of this and the other thread are correctly observed, - // otherwise we will deadlock. - // - // There are two scenarios to consider, depending on whether WAIT or WAKE goes first: - // 1. If we (FUTEX_WAIT) execute first, we'll push ourselves into the waiters queue and - // go to sleep. They (FUTEX_WAKE) will see us in the queue and wake us up. It doesn't - // matter how the addr write is ordered. - // 2. If they (FUTEX_WAKE) execute first, that means the addr write is also before us - // (FUTEX_WAIT). It is crucial that we observe addr's new value. If we see an - // outdated value that happens to equal the expected val, then we'll put ourselves to - // sleep with no one to wake us up, so we end up with a deadlock. This is prevented - // by having a SeqCst fence inside FUTEX_WAKE syscall, and another SeqCst fence here - // in FUTEX_WAIT. The atomic read on addr after the SeqCst fence is guaranteed not to - // see any value older than the addr write immediately before calling FUTEX_WAKE. - // We'll see futex_val != val and return without sleeping. - // - // Note that the fences do not create any happens-before relationship. - // The read sees the write immediately before the fence not because - // one happens after the other, but is instead due to a guarantee unique - // to SeqCst fences that restricts what an atomic read placed AFTER the - // fence can see. The read still has to be atomic, otherwise it's a data - // race. This guarantee cannot be achieved with acquire-release fences - // since they only talk about reads placed BEFORE a fence - and places - // no restrictions on what the read itself can see, only that there is - // a happens-before between the fences IF the read happens to see the - // right value. This is useless to us, since we need the read itself - // to see an up-to-date value. - // - // The above case distinction is valid since both FUTEX_WAIT and FUTEX_WAKE - // contain a SeqCst fence, therefore inducing a total order between the operations. - // It is also critical that the fence, the atomic load, and the comparison in FUTEX_WAIT - // altogether happen atomically. If the other thread's fence in FUTEX_WAKE - // gets interleaved after our fence, then we lose the guarantee on the - // atomic load being up-to-date; if the other thread's write on addr and FUTEX_WAKE - // call are interleaved after the load but before the comparison, then we get a TOCTOU - // race condition, and go to sleep thinking the other thread will wake us up, - // even though they have already finished. - // - // Thankfully, preemptions cannot happen inside a Miri shim, so we do not need to - // do anything special to guarantee fence-load-comparison atomicity. - ecx.atomic_fence(AtomicFenceOrd::SeqCst)?; - // Read an `i32` through the pointer, regardless of any wrapper types. - // It's not uncommon for `addr` to be passed as another type than `*mut i32`, such as `*const AtomicI32`. - // We do an acquire read -- it only seems reasonable that if we observe a value here, we - // actually establish an ordering with that value. - let futex_val = ecx.read_scalar_atomic(&addr, AtomicReadOrd::Acquire)?.to_i32()?; - if val == futex_val { - // The value still matches, so we block the thread and make it wait for FUTEX_WAKE. - - // This cannot fail since we already did an atomic acquire read on that pointer. - // Acquire reads are only allowed on mutable memory. - let futex_ref = ecx - .get_sync_or_init(addr.ptr(), |_| LinuxFutex { futex: Default::default() }) - .unwrap() - .futex - .clone(); - - ecx.futex_wait( - futex_ref, - bitset, - timeout, - Scalar::from_target_isize(0, ecx), // retval_succ - Scalar::from_target_isize(-1, ecx), // retval_timeout - dest.clone(), - LibcError("ETIMEDOUT"), // errno_timeout - ); - } else { - // The futex value doesn't match the expected value, so we return failure - // right away without sleeping: -1 and errno set to EAGAIN. - return ecx.set_last_error_and_return(LibcError("EAGAIN"), dest); - } - } - // FUTEX_WAKE: (int *addr, int op = FUTEX_WAKE, int val) - // Wakes at most `val` threads waiting on the futex at `addr`. - // Returns the amount of threads woken up. - // Does not access the futex value at *addr. - // FUTEX_WAKE_BITSET: (int *addr, int op = FUTEX_WAKE, int val, const timespect *_unused, int *_unused, unsigned int bitset) - // Same as FUTEX_WAKE, but allows you to specify a bitset to select which threads to wake up. - op if op == futex_wake || op == futex_wake_bitset => { - let Some(futex_ref) = - ecx.get_sync_or_init(addr.ptr(), |_| LinuxFutex { futex: Default::default() }) - else { - // No AllocId, or no live allocation at that AllocId. - // Return an error code. (That seems nicer than silently doing something non-intuitive.) - // This means that if an address gets reused by a new allocation, - // we'll use an independent futex queue for this... that seems acceptable. - return ecx.set_last_error_and_return(LibcError("EFAULT"), dest); - }; - let futex_ref = futex_ref.futex.clone(); - - let bitset = if op == futex_wake_bitset { - let [_, _, _, _, timeout, uaddr2, bitset] = - check_min_arg_count("`syscall(SYS_futex, FUTEX_WAKE_BITSET, ...)`", args)?; - let _timeout = ecx.read_pointer(timeout)?; - let _uaddr2 = ecx.read_pointer(uaddr2)?; - ecx.read_scalar(bitset)?.to_u32()? - } else { - u32::MAX - }; - if bitset == 0 { - return ecx.set_last_error_and_return(LibcError("EINVAL"), dest); - } - // Together with the SeqCst fence in futex_wait, this makes sure that futex_wait - // will see the latest value on addr which could be changed by our caller - // before doing the syscall. - ecx.atomic_fence(AtomicFenceOrd::SeqCst)?; - let mut n = 0; - #[expect(clippy::arithmetic_side_effects)] - for _ in 0..val { - if ecx.futex_wake(&futex_ref, bitset)? { - n += 1; - } else { - break; - } - } - ecx.write_scalar(Scalar::from_target_isize(n, ecx), dest)?; - } - op => throw_unsup_format!("Miri does not support `futex` syscall with op={}", op), - } - - interp_ok(()) -} diff --git a/src/tools/miri/src/shims/unix/linux/syscall.rs b/src/tools/miri/src/shims/unix/linux/syscall.rs deleted file mode 100644 index 9f6935f096b..00000000000 --- a/src/tools/miri/src/shims/unix/linux/syscall.rs +++ /dev/null @@ -1,63 +0,0 @@ -use rustc_abi::ExternAbi; -use rustc_span::Symbol; - -use self::shims::unix::linux::eventfd::EvalContextExt as _; -use crate::helpers::check_min_arg_count; -use crate::shims::unix::linux::sync::futex; -use crate::*; - -pub fn syscall<'tcx>( - ecx: &mut MiriInterpCx<'tcx>, - link_name: Symbol, - abi: ExternAbi, - args: &[OpTy<'tcx>], - dest: &MPlaceTy<'tcx>, -) -> InterpResult<'tcx> { - // We do not use `check_shim` here because `syscall` is variadic. The argument - // count is checked bellow. - ecx.check_abi_and_shim_symbol_clash(abi, ExternAbi::C { unwind: false }, link_name)?; - // The syscall variadic function is legal to call with more arguments than needed, - // extra arguments are simply ignored. The important check is that when we use an - // argument, we have to also check all arguments *before* it to ensure that they - // have the right type. - - let sys_getrandom = ecx.eval_libc("SYS_getrandom").to_target_usize(ecx)?; - let sys_futex = ecx.eval_libc("SYS_futex").to_target_usize(ecx)?; - let sys_eventfd2 = ecx.eval_libc("SYS_eventfd2").to_target_usize(ecx)?; - - let [op] = check_min_arg_count("syscall", args)?; - match ecx.read_target_usize(op)? { - // `libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)` - // is called if a `HashMap` is created the regular way (e.g. HashMap). - num if num == sys_getrandom => { - // Used by getrandom 0.1 - // The first argument is the syscall id, so skip over it. - let [_, ptr, len, flags] = check_min_arg_count("syscall(SYS_getrandom, ...)", args)?; - - let ptr = ecx.read_pointer(ptr)?; - let len = ecx.read_target_usize(len)?; - // The only supported flags are GRND_RANDOM and GRND_NONBLOCK, - // neither of which have any effect on our current PRNG. - // See for a discussion of argument sizes. - let _flags = ecx.read_scalar(flags)?.to_i32()?; - - ecx.gen_random(ptr, len)?; - ecx.write_scalar(Scalar::from_target_usize(len, ecx), dest)?; - } - // `futex` is used by some synchronization primitives. - num if num == sys_futex => { - futex(ecx, args, dest)?; - } - num if num == sys_eventfd2 => { - let [_, initval, flags] = check_min_arg_count("syscall(SYS_evetfd2, ...)", args)?; - - let result = ecx.eventfd(initval, flags)?; - ecx.write_int(result.to_i32()?, dest)?; - } - num => { - throw_unsup_format!("syscall: unsupported syscall number {num}"); - } - }; - - interp_ok(()) -} diff --git a/src/tools/miri/src/shims/unix/linux_like/epoll.rs b/src/tools/miri/src/shims/unix/linux_like/epoll.rs new file mode 100644 index 00000000000..b20b12528db --- /dev/null +++ b/src/tools/miri/src/shims/unix/linux_like/epoll.rs @@ -0,0 +1,663 @@ +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io; +use std::rc::{Rc, Weak}; +use std::time::Duration; + +use crate::concurrency::VClock; +use crate::shims::unix::fd::{FdId, FileDescriptionRef, WeakFileDescriptionRef}; +use crate::shims::unix::*; +use crate::*; + +/// An `Epoll` file descriptor connects file handles and epoll events +#[derive(Clone, Debug, Default)] +struct Epoll { + /// A map of EpollEventInterests registered under this epoll instance. + /// Each entry is differentiated using FdId and file descriptor value. + interest_list: RefCell>>>, + /// A map of EpollEventInstance that will be returned when `epoll_wait` is called. + /// Similar to interest_list, the entry is also differentiated using FdId + /// and file descriptor value. + // This is an Rc because EpollInterest need to hold a reference to update + // it. + ready_list: Rc, + /// A list of thread ids blocked on this epoll instance. + thread_id: RefCell>, +} + +/// EpollEventInstance contains information that will be returned by epoll_wait. +#[derive(Debug)] +pub struct EpollEventInstance { + /// Xor-ed event types that happened to the file description. + events: u32, + /// Original data retrieved from `epoll_event` during `epoll_ctl`. + data: u64, + /// The release clock associated with this event. + clock: VClock, +} + +impl EpollEventInstance { + pub fn new(events: u32, data: u64) -> EpollEventInstance { + EpollEventInstance { events, data, clock: Default::default() } + } +} + +/// EpollEventInterest registers the file description information to an epoll +/// instance during a successful `epoll_ctl` call. It also stores additional +/// information needed to check and update readiness state for `epoll_wait`. +/// +/// `events` and `data` field matches the `epoll_event` struct defined +/// by the epoll_ctl man page. For more information +/// see the man page: +/// +/// +#[derive(Clone, Debug)] +pub struct EpollEventInterest { + /// The file descriptor value of the file description registered. + /// This is only used for ready_list, to inform userspace which FD triggered an event. + /// For that, it is crucial to preserve the original FD number. + /// This FD number must never be "dereferenced" to a file description inside Miri. + fd_num: i32, + /// The events bitmask retrieved from `epoll_event`. + events: u32, + /// The data retrieved from `epoll_event`. + /// libc's data field in epoll_event can store integer or pointer, + /// but only u64 is supported for now. + /// + data: u64, + /// Ready list of the epoll instance under which this EpollEventInterest is registered. + ready_list: Rc, + /// The epoll file description that this EpollEventInterest is registered under. + weak_epfd: WeakFileDescriptionRef, +} + +/// EpollReadyEvents reflects the readiness of a file description. +pub struct EpollReadyEvents { + /// The associated file is available for read(2) operations, in the sense that a read will not block. + /// (I.e., returning EOF is considered "ready".) + pub epollin: bool, + /// The associated file is available for write(2) operations, in the sense that a write will not block. + pub epollout: bool, + /// Stream socket peer closed connection, or shut down writing + /// half of connection. + pub epollrdhup: bool, + /// For stream socket, this event merely indicates that the peer + /// closed its end of the channel. + /// Unlike epollrdhup, this should only be set when the stream is fully closed. + /// epollrdhup also gets set when only the write half is closed, which is possible + /// via `shutdown(_, SHUT_WR)`. + pub epollhup: bool, + /// Error condition happened on the associated file descriptor. + pub epollerr: bool, +} + +#[derive(Debug, Default)] +struct ReadyList { + mapping: RefCell>, +} + +impl EpollReadyEvents { + pub fn new() -> Self { + EpollReadyEvents { + epollin: false, + epollout: false, + epollrdhup: false, + epollhup: false, + epollerr: false, + } + } + + pub fn get_event_bitmask<'tcx>(&self, ecx: &MiriInterpCx<'tcx>) -> u32 { + let epollin = ecx.eval_libc_u32("EPOLLIN"); + let epollout = ecx.eval_libc_u32("EPOLLOUT"); + let epollrdhup = ecx.eval_libc_u32("EPOLLRDHUP"); + let epollhup = ecx.eval_libc_u32("EPOLLHUP"); + let epollerr = ecx.eval_libc_u32("EPOLLERR"); + + let mut bitmask = 0; + if self.epollin { + bitmask |= epollin; + } + if self.epollout { + bitmask |= epollout; + } + if self.epollrdhup { + bitmask |= epollrdhup; + } + if self.epollhup { + bitmask |= epollhup; + } + if self.epollerr { + bitmask |= epollerr; + } + bitmask + } +} + +impl Epoll { + fn get_ready_list(&self) -> Rc { + Rc::clone(&self.ready_list) + } +} + +impl FileDescription for Epoll { + fn name(&self) -> &'static str { + "epoll" + } + + fn close<'tcx>( + self: Box, + _communicate_allowed: bool, + _ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx, io::Result<()>> { + interp_ok(Ok(())) + } +} + +/// The table of all EpollEventInterest. +/// The BTreeMap key is the FdId of an active file description registered with +/// any epoll instance. The value is a list of EpollEventInterest associated +/// with that file description. +pub struct EpollInterestTable(BTreeMap>>>); + +impl EpollInterestTable { + pub(crate) fn new() -> Self { + EpollInterestTable(BTreeMap::new()) + } + + pub fn insert_epoll_interest(&mut self, id: FdId, fd: Weak>) { + match self.0.get_mut(&id) { + Some(fds) => { + fds.push(fd); + } + None => { + let vec = vec![fd]; + self.0.insert(id, vec); + } + } + } + + pub fn get_epoll_interest(&self, id: FdId) -> Option<&Vec>>> { + self.0.get(&id) + } + + pub fn get_epoll_interest_mut( + &mut self, + id: FdId, + ) -> Option<&mut Vec>>> { + self.0.get_mut(&id) + } + + pub fn remove(&mut self, id: FdId) { + self.0.remove(&id); + } +} + +impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} +pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { + /// This function returns a file descriptor referring to the new `Epoll` instance. This file + /// descriptor is used for all subsequent calls to the epoll interface. If the `flags` argument + /// is 0, then this function is the same as `epoll_create()`. + /// + /// + fn epoll_create1(&mut self, flags: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { + let this = self.eval_context_mut(); + + let flags = this.read_scalar(flags)?.to_i32()?; + + let epoll_cloexec = this.eval_libc_i32("EPOLL_CLOEXEC"); + + // Miri does not support exec, so EPOLL_CLOEXEC flag has no effect. + if flags != epoll_cloexec && flags != 0 { + throw_unsup_format!( + "epoll_create1: flag {:#x} is unsupported, only 0 or EPOLL_CLOEXEC are allowed", + flags + ); + } + + let fd = this.machine.fds.insert_new(Epoll::default()); + interp_ok(Scalar::from_i32(fd)) + } + + /// This function performs control operations on the `Epoll` instance referred to by the file + /// descriptor `epfd`. It requests that the operation `op` be performed for the target file + /// descriptor, `fd`. + /// + /// Valid values for the op argument are: + /// `EPOLL_CTL_ADD` - Register the target file descriptor `fd` on the `Epoll` instance referred + /// to by the file descriptor `epfd` and associate the event `event` with the internal file + /// linked to `fd`. + /// `EPOLL_CTL_MOD` - Change the event `event` associated with the target file descriptor `fd`. + /// `EPOLL_CTL_DEL` - Deregister the target file descriptor `fd` from the `Epoll` instance + /// referred to by `epfd`. The `event` is ignored and can be null. + /// + /// + fn epoll_ctl( + &mut self, + epfd: &OpTy<'tcx>, + op: &OpTy<'tcx>, + fd: &OpTy<'tcx>, + event: &OpTy<'tcx>, + ) -> InterpResult<'tcx, Scalar> { + let this = self.eval_context_mut(); + + let epfd_value = this.read_scalar(epfd)?.to_i32()?; + let op = this.read_scalar(op)?.to_i32()?; + let fd = this.read_scalar(fd)?.to_i32()?; + let event = this.deref_pointer_as(event, this.libc_ty_layout("epoll_event"))?; + + let epoll_ctl_add = this.eval_libc_i32("EPOLL_CTL_ADD"); + let epoll_ctl_mod = this.eval_libc_i32("EPOLL_CTL_MOD"); + let epoll_ctl_del = this.eval_libc_i32("EPOLL_CTL_DEL"); + let epollin = this.eval_libc_u32("EPOLLIN"); + let epollout = this.eval_libc_u32("EPOLLOUT"); + let epollrdhup = this.eval_libc_u32("EPOLLRDHUP"); + let epollet = this.eval_libc_u32("EPOLLET"); + let epollhup = this.eval_libc_u32("EPOLLHUP"); + let epollerr = this.eval_libc_u32("EPOLLERR"); + + // Throw EINVAL if epfd and fd have the same value. + if epfd_value == fd { + return this.set_last_error_and_return_i32(LibcError("EINVAL")); + } + + // Check if epfd is a valid epoll file descriptor. + let Some(epfd) = this.machine.fds.get(epfd_value) else { + return this.set_last_error_and_return_i32(LibcError("EBADF")); + }; + let epoll_file_description = epfd + .downcast::() + .ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_ctl`"))?; + + let mut interest_list = epoll_file_description.interest_list.borrow_mut(); + let ready_list = &epoll_file_description.ready_list; + + let Some(fd_ref) = this.machine.fds.get(fd) else { + return this.set_last_error_and_return_i32(LibcError("EBADF")); + }; + let id = fd_ref.get_id(); + + if op == epoll_ctl_add || op == epoll_ctl_mod { + // Read event bitmask and data from epoll_event passed by caller. + let mut events = this.read_scalar(&this.project_field(&event, 0)?)?.to_u32()?; + let data = this.read_scalar(&this.project_field(&event, 1)?)?.to_u64()?; + + // Unset the flag we support to discover if any unsupported flags are used. + let mut flags = events; + // epoll_wait(2) will always wait for epollhup and epollerr; it is not + // necessary to set it in events when calling epoll_ctl(). + // So we will always set these two event types. + events |= epollhup; + events |= epollerr; + + if events & epollet != epollet { + // We only support edge-triggered notification for now. + throw_unsup_format!("epoll_ctl: epollet flag must be included."); + } else { + flags &= !epollet; + } + if flags & epollin == epollin { + flags &= !epollin; + } + if flags & epollout == epollout { + flags &= !epollout; + } + if flags & epollrdhup == epollrdhup { + flags &= !epollrdhup; + } + if flags & epollhup == epollhup { + flags &= !epollhup; + } + if flags & epollerr == epollerr { + flags &= !epollerr; + } + if flags != 0 { + throw_unsup_format!( + "epoll_ctl: encountered unknown unsupported flags {:#x}", + flags + ); + } + + let epoll_key = (id, fd); + + // Check the existence of fd in the interest list. + if op == epoll_ctl_add { + if interest_list.contains_key(&epoll_key) { + return this.set_last_error_and_return_i32(LibcError("EEXIST")); + } + } else { + if !interest_list.contains_key(&epoll_key) { + return this.set_last_error_and_return_i32(LibcError("ENOENT")); + } + } + + // Create an epoll_interest. + let interest = Rc::new(RefCell::new(EpollEventInterest { + fd_num: fd, + events, + data, + ready_list: Rc::clone(ready_list), + weak_epfd: epfd.downgrade(), + })); + + if op == epoll_ctl_add { + // Insert an epoll_interest to global epoll_interest list. + this.machine.epoll_interests.insert_epoll_interest(id, Rc::downgrade(&interest)); + interest_list.insert(epoll_key, Rc::clone(&interest)); + } else { + // Directly modify the epoll_interest so the global epoll_event_interest table + // will be updated too. + let mut epoll_interest = interest_list.get_mut(&epoll_key).unwrap().borrow_mut(); + epoll_interest.events = events; + epoll_interest.data = data; + } + + // Notification will be returned for current epfd if there is event in the file + // descriptor we registered. + check_and_update_one_event_interest(&fd_ref, interest, id, this)?; + interp_ok(Scalar::from_i32(0)) + } else if op == epoll_ctl_del { + let epoll_key = (id, fd); + + // Remove epoll_event_interest from interest_list. + let Some(epoll_interest) = interest_list.remove(&epoll_key) else { + return this.set_last_error_and_return_i32(LibcError("ENOENT")); + }; + // All related Weak will fail to upgrade after the drop. + drop(epoll_interest); + + // Remove related epoll_interest from ready list. + ready_list.mapping.borrow_mut().remove(&epoll_key); + + // Remove dangling EpollEventInterest from its global table. + // .unwrap() below should succeed because the file description id must have registered + // at least one epoll_interest, if not, it will fail when removing epoll_interest from + // interest list. + this.machine + .epoll_interests + .get_epoll_interest_mut(id) + .unwrap() + .retain(|event| event.upgrade().is_some()); + + interp_ok(Scalar::from_i32(0)) + } else { + throw_unsup_format!("unsupported epoll_ctl operation: {op}"); + } + } + + /// The `epoll_wait()` system call waits for events on the `Epoll` + /// instance referred to by the file descriptor `epfd`. The buffer + /// pointed to by `events` is used to return information from the ready + /// list about file descriptors in the interest list that have some + /// events available. Up to `maxevents` are returned by `epoll_wait()`. + /// The `maxevents` argument must be greater than zero. + /// + /// The `timeout` argument specifies the number of milliseconds that + /// `epoll_wait()` will block. Time is measured against the + /// CLOCK_MONOTONIC clock. If the timeout is zero, the function will not block, + /// while if the timeout is -1, the function will block + /// until at least one event has been retrieved (or an error + /// occurred). + /// + /// A call to `epoll_wait()` will block until either: + /// • a file descriptor delivers an event; + /// • the call is interrupted by a signal handler; or + /// • the timeout expires. + /// + /// Note that the timeout interval will be rounded up to the system + /// clock granularity, and kernel scheduling delays mean that the + /// blocking interval may overrun by a small amount. Specifying a + /// timeout of -1 causes `epoll_wait()` to block indefinitely, while + /// specifying a timeout equal to zero cause `epoll_wait()` to return + /// immediately, even if no events are available. + /// + /// On success, `epoll_wait()` returns the number of file descriptors + /// ready for the requested I/O, or zero if no file descriptor became + /// ready during the requested timeout milliseconds. On failure, + /// `epoll_wait()` returns -1 and errno is set to indicate the error. + /// + /// + fn epoll_wait( + &mut self, + epfd: &OpTy<'tcx>, + events_op: &OpTy<'tcx>, + maxevents: &OpTy<'tcx>, + timeout: &OpTy<'tcx>, + dest: &MPlaceTy<'tcx>, + ) -> InterpResult<'tcx> { + let this = self.eval_context_mut(); + + let epfd_value = this.read_scalar(epfd)?.to_i32()?; + let events = this.read_immediate(events_op)?; + let maxevents = this.read_scalar(maxevents)?.to_i32()?; + let timeout = this.read_scalar(timeout)?.to_i32()?; + + if epfd_value <= 0 || maxevents <= 0 { + return this.set_last_error_and_return(LibcError("EINVAL"), dest); + } + + // This needs to come after the maxevents value check, or else maxevents.try_into().unwrap() + // will fail. + let event = this.deref_pointer_as( + &events, + this.libc_array_ty_layout("epoll_event", maxevents.try_into().unwrap()), + )?; + + let Some(epfd) = this.machine.fds.get(epfd_value) else { + return this.set_last_error_and_return(LibcError("EBADF"), dest); + }; + // Create a weak ref of epfd and pass it to callback so we will make sure that epfd + // is not close after the thread unblocks. + let weak_epfd = epfd.downgrade(); + + // We just need to know if the ready list is empty and borrow the thread_ids out. + // The whole logic is wrapped inside a block so we don't need to manually drop epfd later. + let ready_list_empty; + let mut thread_ids; + { + let epoll_file_description = epfd + .downcast::() + .ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_wait`"))?; + ready_list_empty = epoll_file_description.ready_list.mapping.borrow().is_empty(); + thread_ids = epoll_file_description.thread_id.borrow_mut(); + } + if timeout == 0 || !ready_list_empty { + // If the ready list is not empty, or the timeout is 0, we can return immediately. + return_ready_list(epfd_value, weak_epfd, dest, &event, this)?; + } else { + // Blocking + let timeout = match timeout { + 0.. => { + let duration = Duration::from_millis(timeout.try_into().unwrap()); + Some((TimeoutClock::Monotonic, TimeoutAnchor::Relative, duration)) + } + -1 => None, + ..-1 => { + throw_unsup_format!( + "epoll_wait: Only timeout values greater than or equal to -1 are supported." + ); + } + }; + thread_ids.push(this.active_thread()); + let dest = dest.clone(); + this.block_thread( + BlockReason::Epoll, + timeout, + callback!( + @capture<'tcx> { + epfd_value: i32, + weak_epfd: WeakFileDescriptionRef, + dest: MPlaceTy<'tcx>, + event: MPlaceTy<'tcx>, + } + @unblock = |this| { + return_ready_list(epfd_value, weak_epfd, &dest, &event, this)?; + interp_ok(()) + } + @timeout = |this| { + // No notification after blocking timeout. + let Some(epfd) = weak_epfd.upgrade() else { + throw_unsup_format!("epoll FD {epfd_value} got closed while blocking.") + }; + // Remove the current active thread_id from the blocked thread_id list. + epfd.downcast::() + .ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_wait`"))? + .thread_id.borrow_mut() + .retain(|&id| id != this.active_thread()); + this.write_int(0, &dest)?; + interp_ok(()) + } + ), + ); + } + interp_ok(()) + } + + /// For a specific file description, get its ready events and update the corresponding ready + /// list. This function should be called whenever an event causes more bytes or an EOF to become + /// newly readable from an FD, and whenever more bytes can be written to an FD or no more future + /// writes are possible. + /// + /// This *will* report an event if anyone is subscribed to it, without any further filtering, so + /// do not call this function when an FD didn't have anything happen to it! + fn check_and_update_readiness( + &mut self, + fd_ref: &FileDescriptionRef, + ) -> InterpResult<'tcx, ()> { + let this = self.eval_context_mut(); + let id = fd_ref.get_id(); + let mut waiter = Vec::new(); + // Get a list of EpollEventInterest that is associated to a specific file description. + if let Some(epoll_interests) = this.machine.epoll_interests.get_epoll_interest(id) { + for weak_epoll_interest in epoll_interests { + if let Some(epoll_interest) = weak_epoll_interest.upgrade() { + let is_updated = check_and_update_one_event_interest( + fd_ref, + epoll_interest.clone(), + id, + this, + )?; + if is_updated { + // Edge-triggered notification only notify one thread even if there are + // multiple threads blocked on the same epfd. + + // This unwrap can never fail because if the current epoll instance were + // closed, the upgrade of weak_epoll_interest + // above would fail. This guarantee holds because only the epoll instance + // holds a strong ref to epoll_interest. + let epfd = epoll_interest.borrow().weak_epfd.upgrade().unwrap(); + // FIXME: We can randomly pick a thread to unblock. + + let epoll = epfd.downcast::().unwrap(); + + if let Some(thread_id) = epoll.thread_id.borrow_mut().pop() { + waiter.push(thread_id); + }; + } + } + } + } + waiter.sort(); + waiter.dedup(); + for thread_id in waiter { + this.unblock_thread(thread_id, BlockReason::Epoll)?; + } + interp_ok(()) + } +} + +/// This function takes in ready list and returns EpollEventInstance with file description +/// that is not closed. +fn ready_list_next( + ecx: &MiriInterpCx<'_>, + ready_list: &mut BTreeMap<(FdId, i32), EpollEventInstance>, +) -> Option { + while let Some((epoll_key, epoll_event_instance)) = ready_list.pop_first() { + // This ensures that we only return events that we are interested. The FD might have been closed since + // the event was generated, in which case we are not interested anymore. + // When a file description is fully closed, it gets removed from `machine.epoll_interests`, + // so we skip events whose FD is not in that map anymore. + if ecx.machine.epoll_interests.get_epoll_interest(epoll_key.0).is_some() { + return Some(epoll_event_instance); + } + } + None +} + +/// This helper function checks whether an epoll notification should be triggered for a specific +/// epoll_interest and, if necessary, triggers the notification, and returns whether the +/// notification was added/updated. Unlike check_and_update_readiness, this function sends a +/// notification to only one epoll instance. +fn check_and_update_one_event_interest<'tcx>( + fd_ref: &FileDescriptionRef, + interest: Rc>, + id: FdId, + ecx: &MiriInterpCx<'tcx>, +) -> InterpResult<'tcx, bool> { + // Get the bitmask of ready events for a file description. + let ready_events_bitmask = fd_ref.get_epoll_ready_events()?.get_event_bitmask(ecx); + let epoll_event_interest = interest.borrow(); + // This checks if any of the events specified in epoll_event_interest.events + // match those in ready_events. + let flags = epoll_event_interest.events & ready_events_bitmask; + // If there is any event that we are interested in being specified as ready, + // insert an epoll_return to the ready list. + if flags != 0 { + let epoll_key = (id, epoll_event_interest.fd_num); + let ready_list = &mut epoll_event_interest.ready_list.mapping.borrow_mut(); + let mut event_instance = EpollEventInstance::new(flags, epoll_event_interest.data); + // If we are tracking data races, remember the current clock so we can sync with it later. + ecx.release_clock(|clock| { + event_instance.clock.clone_from(clock); + }); + // Triggers the notification by inserting it to the ready list. + ready_list.insert(epoll_key, event_instance); + interp_ok(true) + } else { + interp_ok(false) + } +} + +/// Stores the ready list of the `epfd` epoll instance into `events` (which must be an array), +/// and the number of returned events into `dest`. +fn return_ready_list<'tcx>( + epfd_value: i32, + weak_epfd: WeakFileDescriptionRef, + dest: &MPlaceTy<'tcx>, + events: &MPlaceTy<'tcx>, + ecx: &mut MiriInterpCx<'tcx>, +) -> InterpResult<'tcx> { + let Some(epfd) = weak_epfd.upgrade() else { + throw_unsup_format!("epoll FD {epfd_value} got closed while blocking.") + }; + + let epoll_file_description = epfd + .downcast::() + .ok_or_else(|| err_unsup_format!("non-epoll FD passed to `epoll_wait`"))?; + + let ready_list = epoll_file_description.get_ready_list(); + + let mut ready_list = ready_list.mapping.borrow_mut(); + let mut num_of_events: i32 = 0; + let mut array_iter = ecx.project_array_fields(events)?; + + while let Some(des) = array_iter.next(ecx)? { + if let Some(epoll_event_instance) = ready_list_next(ecx, &mut ready_list) { + ecx.write_int_fields_named( + &[ + ("events", epoll_event_instance.events.into()), + ("u64", epoll_event_instance.data.into()), + ], + &des.1, + )?; + // Synchronize waking thread with the event of interest. + ecx.acquire_clock(&epoll_event_instance.clock); + + num_of_events = num_of_events.strict_add(1); + } else { + break; + } + } + ecx.write_int(num_of_events, dest)?; + interp_ok(()) +} diff --git a/src/tools/miri/src/shims/unix/linux_like/eventfd.rs b/src/tools/miri/src/shims/unix/linux_like/eventfd.rs new file mode 100644 index 00000000000..61c91877946 --- /dev/null +++ b/src/tools/miri/src/shims/unix/linux_like/eventfd.rs @@ -0,0 +1,330 @@ +//! Linux `eventfd` implementation. +use std::cell::{Cell, RefCell}; +use std::io; +use std::io::ErrorKind; + +use crate::concurrency::VClock; +use crate::shims::unix::fd::{FileDescriptionRef, WeakFileDescriptionRef}; +use crate::shims::unix::linux_like::epoll::{EpollReadyEvents, EvalContextExt as _}; +use crate::shims::unix::*; +use crate::*; + +/// Maximum value that the eventfd counter can hold. +const MAX_COUNTER: u64 = u64::MAX - 1; + +/// A kind of file descriptor created by `eventfd`. +/// The `Event` type isn't currently written to by `eventfd`. +/// The interface is meant to keep track of objects associated +/// with a file descriptor. For more information see the man +/// page below: +/// +/// +#[derive(Debug)] +struct Event { + /// The object contains an unsigned 64-bit integer (uint64_t) counter that is maintained by the + /// kernel. This counter is initialized with the value specified in the argument initval. + counter: Cell, + is_nonblock: bool, + clock: RefCell, + /// A list of thread ids blocked on eventfd::read. + blocked_read_tid: RefCell>, + /// A list of thread ids blocked on eventfd::write. + blocked_write_tid: RefCell>, +} + +impl FileDescription for Event { + fn name(&self) -> &'static str { + "event" + } + + fn get_epoll_ready_events<'tcx>(&self) -> InterpResult<'tcx, EpollReadyEvents> { + // We only check the status of EPOLLIN and EPOLLOUT flags for eventfd. If other event flags + // need to be supported in the future, the check should be added here. + + interp_ok(EpollReadyEvents { + epollin: self.counter.get() != 0, + epollout: self.counter.get() != MAX_COUNTER, + ..EpollReadyEvents::new() + }) + } + + fn close<'tcx>( + self: Box, + _communicate_allowed: bool, + _ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx, io::Result<()>> { + interp_ok(Ok(())) + } + + /// Read the counter in the buffer and return the counter if succeeded. + fn read<'tcx>( + &self, + self_ref: &FileDescriptionRef, + _communicate_allowed: bool, + ptr: Pointer, + len: usize, + dest: &MPlaceTy<'tcx>, + ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx> { + // We're treating the buffer as a `u64`. + let ty = ecx.machine.layouts.u64; + // Check the size of slice, and return error only if the size of the slice < 8. + if len < ty.size.bytes_usize() { + return ecx.set_last_error_and_return(ErrorKind::InvalidInput, dest); + } + + // eventfd read at the size of u64. + let buf_place = ecx.ptr_to_mplace_unaligned(ptr, ty); + + let weak_eventfd = self_ref.downgrade(); + eventfd_read(buf_place, dest, weak_eventfd, ecx) + } + + /// A write call adds the 8-byte integer value supplied in + /// its buffer (in native endianness) to the counter. The maximum value that may be + /// stored in the counter is the largest unsigned 64-bit value + /// minus 1 (i.e., 0xfffffffffffffffe). If the addition would + /// cause the counter's value to exceed the maximum, then the + /// write either blocks until a read is performed on the + /// file descriptor, or fails with the error EAGAIN if the + /// file descriptor has been made nonblocking. + /// + /// A write fails with the error EINVAL if the size of the + /// supplied buffer is less than 8 bytes, or if an attempt is + /// made to write the value 0xffffffffffffffff. + fn write<'tcx>( + &self, + self_ref: &FileDescriptionRef, + _communicate_allowed: bool, + ptr: Pointer, + len: usize, + dest: &MPlaceTy<'tcx>, + ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx> { + // We're treating the buffer as a `u64`. + let ty = ecx.machine.layouts.u64; + // Check the size of slice, and return error only if the size of the slice < 8. + if len < ty.layout.size.bytes_usize() { + return ecx.set_last_error_and_return(ErrorKind::InvalidInput, dest); + } + + // Read the user-supplied value from the pointer. + let buf_place = ecx.ptr_to_mplace_unaligned(ptr, ty); + let num = ecx.read_scalar(&buf_place)?.to_u64()?; + + // u64::MAX as input is invalid because the maximum value of counter is u64::MAX - 1. + if num == u64::MAX { + return ecx.set_last_error_and_return(ErrorKind::InvalidInput, dest); + } + // If the addition does not let the counter to exceed the maximum value, update the counter. + // Else, block. + let weak_eventfd = self_ref.downgrade(); + eventfd_write(num, buf_place, dest, weak_eventfd, ecx) + } +} + +impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} +pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { + /// This function creates an `Event` that is used as an event wait/notify mechanism by + /// user-space applications, and by the kernel to notify user-space applications of events. + /// The `Event` contains an `u64` counter maintained by the kernel. The counter is initialized + /// with the value specified in the `initval` argument. + /// + /// A new file descriptor referring to the `Event` is returned. The `read`, `write`, `poll`, + /// `select`, and `close` operations can be performed on the file descriptor. For more + /// information on these operations, see the man page linked below. + /// + /// The `flags` are not currently implemented for eventfd. + /// The `flags` may be bitwise ORed to change the behavior of `eventfd`: + /// `EFD_CLOEXEC` - Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor. + /// `EFD_NONBLOCK` - Set the `O_NONBLOCK` file status flag on the new open file description. + /// `EFD_SEMAPHORE` - miri does not support semaphore-like semantics. + /// + /// + fn eventfd(&mut self, val: &OpTy<'tcx>, flags: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { + let this = self.eval_context_mut(); + + let val = this.read_scalar(val)?.to_u32()?; + let mut flags = this.read_scalar(flags)?.to_i32()?; + + let efd_cloexec = this.eval_libc_i32("EFD_CLOEXEC"); + let efd_nonblock = this.eval_libc_i32("EFD_NONBLOCK"); + let efd_semaphore = this.eval_libc_i32("EFD_SEMAPHORE"); + + if flags & efd_semaphore == efd_semaphore { + throw_unsup_format!("eventfd: EFD_SEMAPHORE is unsupported"); + } + + let mut is_nonblock = false; + // Unset the flag that we support. + // After unloading, flags != 0 means other flags are used. + if flags & efd_cloexec == efd_cloexec { + // cloexec is ignored because Miri does not support exec. + flags &= !efd_cloexec; + } + if flags & efd_nonblock == efd_nonblock { + flags &= !efd_nonblock; + is_nonblock = true; + } + if flags != 0 { + throw_unsup_format!("eventfd: encountered unknown unsupported flags {:#x}", flags); + } + + let fds = &mut this.machine.fds; + + let fd_value = fds.insert_new(Event { + counter: Cell::new(val.into()), + is_nonblock, + clock: RefCell::new(VClock::default()), + blocked_read_tid: RefCell::new(Vec::new()), + blocked_write_tid: RefCell::new(Vec::new()), + }); + + interp_ok(Scalar::from_i32(fd_value)) + } +} + +/// Block thread if the value addition will exceed u64::MAX -1, +/// else just add the user-supplied value to current counter. +fn eventfd_write<'tcx>( + num: u64, + buf_place: MPlaceTy<'tcx>, + dest: &MPlaceTy<'tcx>, + weak_eventfd: WeakFileDescriptionRef, + ecx: &mut MiriInterpCx<'tcx>, +) -> InterpResult<'tcx> { + let Some(eventfd_ref) = weak_eventfd.upgrade() else { + throw_unsup_format!("eventfd FD got closed while blocking.") + }; + + // Since we pass the weak file description ref, it is guaranteed to be + // an eventfd file description. + let eventfd = eventfd_ref.downcast::().unwrap(); + + match eventfd.counter.get().checked_add(num) { + Some(new_count @ 0..=MAX_COUNTER) => { + // Future `read` calls will synchronize with this write, so update the FD clock. + ecx.release_clock(|clock| { + eventfd.clock.borrow_mut().join(clock); + }); + + // Store new counter value. + eventfd.counter.set(new_count); + + // The state changed; we check and update the status of all supported event + // types for current file description. + ecx.check_and_update_readiness(&eventfd_ref)?; + + // Unblock *all* threads previously blocked on `read`. + // We need to take out the blocked thread ids and unblock them together, + // because `unblock_threads` may block them again and end up re-adding the + // thread to the blocked list. + let waiting_threads = std::mem::take(&mut *eventfd.blocked_read_tid.borrow_mut()); + // FIXME: We can randomize the order of unblocking. + for thread_id in waiting_threads { + ecx.unblock_thread(thread_id, BlockReason::Eventfd)?; + } + + // Return how many bytes we consumed from the user-provided buffer. + return ecx.write_int(buf_place.layout.size.bytes(), dest); + } + None | Some(u64::MAX) => { + // We can't update the state, so we have to block. + if eventfd.is_nonblock { + return ecx.set_last_error_and_return(ErrorKind::WouldBlock, dest); + } + + let dest = dest.clone(); + + eventfd.blocked_write_tid.borrow_mut().push(ecx.active_thread()); + + ecx.block_thread( + BlockReason::Eventfd, + None, + callback!( + @capture<'tcx> { + num: u64, + buf_place: MPlaceTy<'tcx>, + dest: MPlaceTy<'tcx>, + weak_eventfd: WeakFileDescriptionRef, + } + @unblock = |this| { + // When we get unblocked, try again. + eventfd_write(num, buf_place, &dest, weak_eventfd, this) + } + ), + ); + } + }; + interp_ok(()) +} + +/// Block thread if the current counter is 0, +/// else just return the current counter value to the caller and set the counter to 0. +fn eventfd_read<'tcx>( + buf_place: MPlaceTy<'tcx>, + dest: &MPlaceTy<'tcx>, + weak_eventfd: WeakFileDescriptionRef, + ecx: &mut MiriInterpCx<'tcx>, +) -> InterpResult<'tcx> { + let Some(eventfd_ref) = weak_eventfd.upgrade() else { + throw_unsup_format!("eventfd FD got closed while blocking.") + }; + + // Since we pass the weak file description ref to the callback function, it is guaranteed to be + // an eventfd file description. + let eventfd = eventfd_ref.downcast::().unwrap(); + + // Set counter to 0, get old value. + let counter = eventfd.counter.replace(0); + + // Block when counter == 0. + if counter == 0 { + if eventfd.is_nonblock { + return ecx.set_last_error_and_return(ErrorKind::WouldBlock, dest); + } + let dest = dest.clone(); + + eventfd.blocked_read_tid.borrow_mut().push(ecx.active_thread()); + + ecx.block_thread( + BlockReason::Eventfd, + None, + callback!( + @capture<'tcx> { + buf_place: MPlaceTy<'tcx>, + dest: MPlaceTy<'tcx>, + weak_eventfd: WeakFileDescriptionRef, + } + @unblock = |this| { + // When we get unblocked, try again. + eventfd_read(buf_place, &dest, weak_eventfd, this) + } + ), + ); + } else { + // Synchronize with all prior `write` calls to this FD. + ecx.acquire_clock(&eventfd.clock.borrow()); + + // Return old counter value into user-space buffer. + ecx.write_int(counter, &buf_place)?; + + // The state changed; we check and update the status of all supported event + // types for current file description. + ecx.check_and_update_readiness(&eventfd_ref)?; + + // Unblock *all* threads previously blocked on `write`. + // We need to take out the blocked thread ids and unblock them together, + // because `unblock_threads` may block them again and end up re-adding the + // thread to the blocked list. + let waiting_threads = std::mem::take(&mut *eventfd.blocked_write_tid.borrow_mut()); + // FIXME: We can randomize the order of unblocking. + for thread_id in waiting_threads { + ecx.unblock_thread(thread_id, BlockReason::Eventfd)?; + } + + // Tell userspace how many bytes we put into the buffer. + return ecx.write_int(buf_place.layout.size.bytes(), dest); + } + interp_ok(()) +} diff --git a/src/tools/miri/src/shims/unix/linux_like/mod.rs b/src/tools/miri/src/shims/unix/linux_like/mod.rs new file mode 100644 index 00000000000..1a22539a4ee --- /dev/null +++ b/src/tools/miri/src/shims/unix/linux_like/mod.rs @@ -0,0 +1,4 @@ +pub mod epoll; +pub mod eventfd; +pub mod sync; +pub mod syscall; diff --git a/src/tools/miri/src/shims/unix/linux_like/sync.rs b/src/tools/miri/src/shims/unix/linux_like/sync.rs new file mode 100644 index 00000000000..51124fb2a00 --- /dev/null +++ b/src/tools/miri/src/shims/unix/linux_like/sync.rs @@ -0,0 +1,223 @@ +use crate::concurrency::sync::FutexRef; +use crate::helpers::check_min_arg_count; +use crate::*; + +struct LinuxFutex { + futex: FutexRef, +} + +/// Implementation of the SYS_futex syscall. +/// `args` is the arguments *including* the syscall number. +pub fn futex<'tcx>( + ecx: &mut MiriInterpCx<'tcx>, + args: &[OpTy<'tcx>], + dest: &MPlaceTy<'tcx>, +) -> InterpResult<'tcx> { + // The amount of arguments used depends on the type of futex operation. + // The full futex syscall takes six arguments (excluding the syscall + // number), which is also the maximum amount of arguments a linux syscall + // can take on most architectures. + // However, not all futex operations use all six arguments. The unused ones + // may or may not be left out from the `syscall()` call. + // Therefore we don't use `check_arg_count` here, but only check for the + // number of arguments to fall within a range. + let [_, addr, op, val] = check_min_arg_count("`syscall(SYS_futex, ...)`", args)?; + + // The first three arguments (after the syscall number itself) are the same to all futex operations: + // (int *addr, int op, int val). + // We checked above that these definitely exist. + let addr = ecx.read_pointer(addr)?; + let op = ecx.read_scalar(op)?.to_i32()?; + let val = ecx.read_scalar(val)?.to_i32()?; + + // This is a vararg function so we have to bring our own type for this pointer. + let addr = ecx.ptr_to_mplace(addr, ecx.machine.layouts.i32); + + let futex_private = ecx.eval_libc_i32("FUTEX_PRIVATE_FLAG"); + let futex_wait = ecx.eval_libc_i32("FUTEX_WAIT"); + let futex_wait_bitset = ecx.eval_libc_i32("FUTEX_WAIT_BITSET"); + let futex_wake = ecx.eval_libc_i32("FUTEX_WAKE"); + let futex_wake_bitset = ecx.eval_libc_i32("FUTEX_WAKE_BITSET"); + let futex_realtime = ecx.eval_libc_i32("FUTEX_CLOCK_REALTIME"); + + // FUTEX_PRIVATE enables an optimization that stops it from working across processes. + // Miri doesn't support that anyway, so we ignore that flag. + match op & !futex_private { + // FUTEX_WAIT: (int *addr, int op = FUTEX_WAIT, int val, const timespec *timeout) + // Blocks the thread if *addr still equals val. Wakes up when FUTEX_WAKE is called on the same address, + // or *timeout expires. `timeout == null` for an infinite timeout. + // + // FUTEX_WAIT_BITSET: (int *addr, int op = FUTEX_WAIT_BITSET, int val, const timespec *timeout, int *_ignored, unsigned int bitset) + // This is identical to FUTEX_WAIT, except: + // - The timeout is absolute rather than relative. + // - You can specify the bitset to selecting what WAKE operations to respond to. + op if op & !futex_realtime == futex_wait || op & !futex_realtime == futex_wait_bitset => { + let wait_bitset = op & !futex_realtime == futex_wait_bitset; + + let (timeout, bitset) = if wait_bitset { + let [_, _, _, _, timeout, uaddr2, bitset] = + check_min_arg_count("`syscall(SYS_futex, FUTEX_WAIT_BITSET, ...)`", args)?; + let _timeout = ecx.read_pointer(timeout)?; + let _uaddr2 = ecx.read_pointer(uaddr2)?; + (timeout, ecx.read_scalar(bitset)?.to_u32()?) + } else { + let [_, _, _, _, timeout] = + check_min_arg_count("`syscall(SYS_futex, FUTEX_WAIT, ...)`", args)?; + (timeout, u32::MAX) + }; + + if bitset == 0 { + return ecx.set_last_error_and_return(LibcError("EINVAL"), dest); + } + + let timeout = ecx.deref_pointer_as(timeout, ecx.libc_ty_layout("timespec"))?; + let timeout = if ecx.ptr_is_null(timeout.ptr())? { + None + } else { + let duration = match ecx.read_timespec(&timeout)? { + Some(duration) => duration, + None => { + return ecx.set_last_error_and_return(LibcError("EINVAL"), dest); + } + }; + let timeout_clock = if op & futex_realtime == futex_realtime { + ecx.check_no_isolation( + "`futex` syscall with `op=FUTEX_WAIT` and non-null timeout with `FUTEX_CLOCK_REALTIME`", + )?; + TimeoutClock::RealTime + } else { + TimeoutClock::Monotonic + }; + let timeout_anchor = if wait_bitset { + // FUTEX_WAIT_BITSET uses an absolute timestamp. + TimeoutAnchor::Absolute + } else { + // FUTEX_WAIT uses a relative timestamp. + TimeoutAnchor::Relative + }; + Some((timeout_clock, timeout_anchor, duration)) + }; + // There may be a concurrent thread changing the value of addr + // and then invoking the FUTEX_WAKE syscall. It is critical that the + // effects of this and the other thread are correctly observed, + // otherwise we will deadlock. + // + // There are two scenarios to consider, depending on whether WAIT or WAKE goes first: + // 1. If we (FUTEX_WAIT) execute first, we'll push ourselves into the waiters queue and + // go to sleep. They (FUTEX_WAKE) will see us in the queue and wake us up. It doesn't + // matter how the addr write is ordered. + // 2. If they (FUTEX_WAKE) execute first, that means the addr write is also before us + // (FUTEX_WAIT). It is crucial that we observe addr's new value. If we see an + // outdated value that happens to equal the expected val, then we'll put ourselves to + // sleep with no one to wake us up, so we end up with a deadlock. This is prevented + // by having a SeqCst fence inside FUTEX_WAKE syscall, and another SeqCst fence here + // in FUTEX_WAIT. The atomic read on addr after the SeqCst fence is guaranteed not to + // see any value older than the addr write immediately before calling FUTEX_WAKE. + // We'll see futex_val != val and return without sleeping. + // + // Note that the fences do not create any happens-before relationship. + // The read sees the write immediately before the fence not because + // one happens after the other, but is instead due to a guarantee unique + // to SeqCst fences that restricts what an atomic read placed AFTER the + // fence can see. The read still has to be atomic, otherwise it's a data + // race. This guarantee cannot be achieved with acquire-release fences + // since they only talk about reads placed BEFORE a fence - and places + // no restrictions on what the read itself can see, only that there is + // a happens-before between the fences IF the read happens to see the + // right value. This is useless to us, since we need the read itself + // to see an up-to-date value. + // + // The above case distinction is valid since both FUTEX_WAIT and FUTEX_WAKE + // contain a SeqCst fence, therefore inducing a total order between the operations. + // It is also critical that the fence, the atomic load, and the comparison in FUTEX_WAIT + // altogether happen atomically. If the other thread's fence in FUTEX_WAKE + // gets interleaved after our fence, then we lose the guarantee on the + // atomic load being up-to-date; if the other thread's write on addr and FUTEX_WAKE + // call are interleaved after the load but before the comparison, then we get a TOCTOU + // race condition, and go to sleep thinking the other thread will wake us up, + // even though they have already finished. + // + // Thankfully, preemptions cannot happen inside a Miri shim, so we do not need to + // do anything special to guarantee fence-load-comparison atomicity. + ecx.atomic_fence(AtomicFenceOrd::SeqCst)?; + // Read an `i32` through the pointer, regardless of any wrapper types. + // It's not uncommon for `addr` to be passed as another type than `*mut i32`, such as `*const AtomicI32`. + // We do an acquire read -- it only seems reasonable that if we observe a value here, we + // actually establish an ordering with that value. + let futex_val = ecx.read_scalar_atomic(&addr, AtomicReadOrd::Acquire)?.to_i32()?; + if val == futex_val { + // The value still matches, so we block the thread and make it wait for FUTEX_WAKE. + + // This cannot fail since we already did an atomic acquire read on that pointer. + // Acquire reads are only allowed on mutable memory. + let futex_ref = ecx + .get_sync_or_init(addr.ptr(), |_| LinuxFutex { futex: Default::default() }) + .unwrap() + .futex + .clone(); + + ecx.futex_wait( + futex_ref, + bitset, + timeout, + Scalar::from_target_isize(0, ecx), // retval_succ + Scalar::from_target_isize(-1, ecx), // retval_timeout + dest.clone(), + LibcError("ETIMEDOUT"), // errno_timeout + ); + } else { + // The futex value doesn't match the expected value, so we return failure + // right away without sleeping: -1 and errno set to EAGAIN. + return ecx.set_last_error_and_return(LibcError("EAGAIN"), dest); + } + } + // FUTEX_WAKE: (int *addr, int op = FUTEX_WAKE, int val) + // Wakes at most `val` threads waiting on the futex at `addr`. + // Returns the amount of threads woken up. + // Does not access the futex value at *addr. + // FUTEX_WAKE_BITSET: (int *addr, int op = FUTEX_WAKE, int val, const timespect *_unused, int *_unused, unsigned int bitset) + // Same as FUTEX_WAKE, but allows you to specify a bitset to select which threads to wake up. + op if op == futex_wake || op == futex_wake_bitset => { + let Some(futex_ref) = + ecx.get_sync_or_init(addr.ptr(), |_| LinuxFutex { futex: Default::default() }) + else { + // No AllocId, or no live allocation at that AllocId. + // Return an error code. (That seems nicer than silently doing something non-intuitive.) + // This means that if an address gets reused by a new allocation, + // we'll use an independent futex queue for this... that seems acceptable. + return ecx.set_last_error_and_return(LibcError("EFAULT"), dest); + }; + let futex_ref = futex_ref.futex.clone(); + + let bitset = if op == futex_wake_bitset { + let [_, _, _, _, timeout, uaddr2, bitset] = + check_min_arg_count("`syscall(SYS_futex, FUTEX_WAKE_BITSET, ...)`", args)?; + let _timeout = ecx.read_pointer(timeout)?; + let _uaddr2 = ecx.read_pointer(uaddr2)?; + ecx.read_scalar(bitset)?.to_u32()? + } else { + u32::MAX + }; + if bitset == 0 { + return ecx.set_last_error_and_return(LibcError("EINVAL"), dest); + } + // Together with the SeqCst fence in futex_wait, this makes sure that futex_wait + // will see the latest value on addr which could be changed by our caller + // before doing the syscall. + ecx.atomic_fence(AtomicFenceOrd::SeqCst)?; + let mut n = 0; + #[expect(clippy::arithmetic_side_effects)] + for _ in 0..val { + if ecx.futex_wake(&futex_ref, bitset)? { + n += 1; + } else { + break; + } + } + ecx.write_scalar(Scalar::from_target_isize(n, ecx), dest)?; + } + op => throw_unsup_format!("Miri does not support `futex` syscall with op={}", op), + } + + interp_ok(()) +} diff --git a/src/tools/miri/src/shims/unix/linux_like/syscall.rs b/src/tools/miri/src/shims/unix/linux_like/syscall.rs new file mode 100644 index 00000000000..e9a32a26326 --- /dev/null +++ b/src/tools/miri/src/shims/unix/linux_like/syscall.rs @@ -0,0 +1,63 @@ +use rustc_abi::ExternAbi; +use rustc_span::Symbol; + +use crate::helpers::check_min_arg_count; +use crate::shims::unix::linux_like::eventfd::EvalContextExt as _; +use crate::shims::unix::linux_like::sync::futex; +use crate::*; + +pub fn syscall<'tcx>( + ecx: &mut MiriInterpCx<'tcx>, + link_name: Symbol, + abi: ExternAbi, + args: &[OpTy<'tcx>], + dest: &MPlaceTy<'tcx>, +) -> InterpResult<'tcx> { + // We do not use `check_shim` here because `syscall` is variadic. The argument + // count is checked bellow. + ecx.check_abi_and_shim_symbol_clash(abi, ExternAbi::C { unwind: false }, link_name)?; + // The syscall variadic function is legal to call with more arguments than needed, + // extra arguments are simply ignored. The important check is that when we use an + // argument, we have to also check all arguments *before* it to ensure that they + // have the right type. + + let sys_getrandom = ecx.eval_libc("SYS_getrandom").to_target_usize(ecx)?; + let sys_futex = ecx.eval_libc("SYS_futex").to_target_usize(ecx)?; + let sys_eventfd2 = ecx.eval_libc("SYS_eventfd2").to_target_usize(ecx)?; + + let [op] = check_min_arg_count("syscall", args)?; + match ecx.read_target_usize(op)? { + // `libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)` + // is called if a `HashMap` is created the regular way (e.g. HashMap). + num if num == sys_getrandom => { + // Used by getrandom 0.1 + // The first argument is the syscall id, so skip over it. + let [_, ptr, len, flags] = check_min_arg_count("syscall(SYS_getrandom, ...)", args)?; + + let ptr = ecx.read_pointer(ptr)?; + let len = ecx.read_target_usize(len)?; + // The only supported flags are GRND_RANDOM and GRND_NONBLOCK, + // neither of which have any effect on our current PRNG. + // See for a discussion of argument sizes. + let _flags = ecx.read_scalar(flags)?.to_i32()?; + + ecx.gen_random(ptr, len)?; + ecx.write_scalar(Scalar::from_target_usize(len, ecx), dest)?; + } + // `futex` is used by some synchronization primitives. + num if num == sys_futex => { + futex(ecx, args, dest)?; + } + num if num == sys_eventfd2 => { + let [_, initval, flags] = check_min_arg_count("syscall(SYS_evetfd2, ...)", args)?; + + let result = ecx.eventfd(initval, flags)?; + ecx.write_int(result.to_i32()?, dest)?; + } + num => { + throw_unsup_format!("syscall: unsupported syscall number {num}"); + } + }; + + interp_ok(()) +} diff --git a/src/tools/miri/src/shims/unix/mod.rs b/src/tools/miri/src/shims/unix/mod.rs index c8c25c636ee..0620b57753a 100644 --- a/src/tools/miri/src/shims/unix/mod.rs +++ b/src/tools/miri/src/shims/unix/mod.rs @@ -11,6 +11,7 @@ mod unnamed_socket; mod android; mod freebsd; mod linux; +mod linux_like; mod macos; mod solarish; @@ -18,7 +19,7 @@ mod solarish; pub use self::env::{EvalContextExt as _, UnixEnvVars}; pub use self::fd::{EvalContextExt as _, FdTable, FileDescription}; pub use self::fs::{DirTable, EvalContextExt as _}; -pub use self::linux::epoll::EpollInterestTable; +pub use self::linux_like::epoll::EpollInterestTable; pub use self::mem::EvalContextExt as _; pub use self::sync::EvalContextExt as _; pub use self::thread::{EvalContextExt as _, ThreadNameResult}; diff --git a/src/tools/miri/src/shims/unix/unnamed_socket.rs b/src/tools/miri/src/shims/unix/unnamed_socket.rs index 36575f4b5fb..232f4500dba 100644 --- a/src/tools/miri/src/shims/unix/unnamed_socket.rs +++ b/src/tools/miri/src/shims/unix/unnamed_socket.rs @@ -11,7 +11,7 @@ use rustc_abi::Size; use crate::concurrency::VClock; use crate::shims::unix::fd::{FileDescriptionRef, WeakFileDescriptionRef}; -use crate::shims::unix::linux::epoll::{EpollReadyEvents, EvalContextExt as _}; +use crate::shims::unix::linux_like::epoll::{EpollReadyEvents, EvalContextExt as _}; use crate::shims::unix::*; use crate::*; -- cgit 1.4.1-3-g733a5 From 065d9b5dc3dd21ad0b7d954ed6934e74442843eb Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Mon, 11 Nov 2024 18:54:17 +0300 Subject: Fix the rest of the tests --- src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs | 3 +-- src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs | 3 +-- src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'src/tools') diff --git a/src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs b/src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs index d45dc5af489..e3c42b2701c 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-epoll-blocking.rs @@ -1,5 +1,4 @@ -//@only-target: linux -//@only-target: android +//@only-target: linux android // test_epoll_block_then_unblock and test_epoll_race depend on a deterministic schedule. //@compile-flags: -Zmiri-preemption-rate=0 diff --git a/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs b/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs index 59141cd5dcc..111e639c864 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-epoll-no-blocking.rs @@ -1,5 +1,4 @@ -//@only-target: linux -//@only-target: android +//@only-target: linux android use std::convert::TryInto; diff --git a/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs b/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs index 767ab1065c2..538a157a430 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs @@ -1,5 +1,4 @@ -//@only-target: linux -//@only-target: android +//@only-target: linux android // test_race, test_blocking_read and test_blocking_write depend on a deterministic schedule. //@compile-flags: -Zmiri-preemption-rate=0 -- cgit 1.4.1-3-g733a5 From a05e53b68956f3b183d52e0ba4a46e0fce929a61 Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Mon, 25 Nov 2024 23:59:17 -0500 Subject: attempt to fix miri failing to create file when under weird powershell configurations --- src/tools/miri/cargo-miri/src/phases.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'src/tools') diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs index f1f76fd338c..7ca4f414c20 100644 --- a/src/tools/miri/cargo-miri/src/phases.rs +++ b/src/tools/miri/cargo-miri/src/phases.rs @@ -348,14 +348,17 @@ pub fn phase_rustc(mut args: impl Iterator, phase: RustcPhase) { // Create a stub .d file to stop Cargo from "rebuilding" the crate: // https://github.com/rust-lang/miri/issues/1724#issuecomment-787115693 // As we store a JSON file instead of building the crate here, an empty file is fine. - let dep_info_name = format!( - "{}/{}{}.d", - get_arg_flag_value("--out-dir").unwrap(), + let mut dep_info_name = PathBuf::from(get_arg_flag_value("--out-dir").unwrap()); + dep_info_name.push(format!( + "{}{}.d", get_arg_flag_value("--crate-name").unwrap(), get_arg_flag_value("extra-filename").unwrap_or_default(), - ); + )); if verbose > 0 { - eprintln!("[cargo-miri rustc] writing stub dep-info to `{dep_info_name}`"); + eprintln!( + "[cargo-miri rustc] writing stub dep-info to `{}`", + dep_info_name.display() + ); } File::create(dep_info_name).expect("failed to create fake .d file"); } -- cgit 1.4.1-3-g733a5 From 109c2996461502abc339d841035c800b4b45d9e2 Mon Sep 17 00:00:00 2001 From: tiif Date: Tue, 26 Nov 2024 14:54:26 +0800 Subject: Simplify thread blocking tests --- .../fail-dep/libc/eventfd_block_read_twice.rs | 7 ----- .../fail-dep/libc/eventfd_block_write_twice.rs | 7 ----- .../fail-dep/libc/libc_epoll_block_two_thread.rs | 32 ++++++++-------------- .../libc/libc_epoll_block_two_thread.stderr | 14 +++++----- src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs | 7 ----- 5 files changed, 18 insertions(+), 49 deletions(-) (limited to 'src/tools') diff --git a/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.rs b/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.rs index a9bb4c7eba8..81a96103db4 100644 --- a/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.rs +++ b/src/tools/miri/tests/fail-dep/libc/eventfd_block_read_twice.rs @@ -23,7 +23,6 @@ fn main() { let fd = unsafe { libc::eventfd(0, flags) }; let thread1 = thread::spawn(move || { - thread::park(); let mut buf: [u8; 8] = [0; 8]; // This read will block initially. let res: i64 = unsafe { libc::read(fd, buf.as_mut_ptr().cast(), 8).try_into().unwrap() }; @@ -33,7 +32,6 @@ fn main() { }); let thread2 = thread::spawn(move || { - thread::park(); let mut buf: [u8; 8] = [0; 8]; // This read will block initially, then get unblocked by thread3, then get blocked again // because the `read` in thread1 executes first and set the counter to 0 again. @@ -45,7 +43,6 @@ fn main() { }); let thread3 = thread::spawn(move || { - thread::park(); let sized_8_data = 1_u64.to_ne_bytes(); // Write 1 to the counter, so both thread1 and thread2 will unblock. let res: i64 = unsafe { @@ -55,10 +52,6 @@ fn main() { assert_eq!(res, 8); }); - thread1.thread().unpark(); - thread2.thread().unpark(); - thread3.thread().unpark(); - thread1.join().unwrap(); thread2.join().unwrap(); thread3.join().unwrap(); diff --git a/src/tools/miri/tests/fail-dep/libc/eventfd_block_write_twice.rs b/src/tools/miri/tests/fail-dep/libc/eventfd_block_write_twice.rs index 2212d6c7eb5..7a2a6f4eb1a 100644 --- a/src/tools/miri/tests/fail-dep/libc/eventfd_block_write_twice.rs +++ b/src/tools/miri/tests/fail-dep/libc/eventfd_block_write_twice.rs @@ -28,7 +28,6 @@ fn main() { assert_eq!(res, 8); let thread1 = thread::spawn(move || { - thread::park(); let sized_8_data = (u64::MAX - 1).to_ne_bytes(); let res: i64 = unsafe { libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap() @@ -38,7 +37,6 @@ fn main() { }); let thread2 = thread::spawn(move || { - thread::park(); let sized_8_data = (u64::MAX - 1).to_ne_bytes(); // Write u64::MAX - 1, so the all subsequent write will block. let res: i64 = unsafe { @@ -52,7 +50,6 @@ fn main() { }); let thread3 = thread::spawn(move || { - thread::park(); let mut buf: [u8; 8] = [0; 8]; // This will unblock both `write` in thread1 and thread2. let res: i64 = unsafe { libc::read(fd, buf.as_mut_ptr().cast(), 8).try_into().unwrap() }; @@ -61,10 +58,6 @@ fn main() { assert_eq!(counter, (u64::MAX - 1)); }); - thread1.thread().unpark(); - thread2.thread().unpark(); - thread3.thread().unpark(); - thread1.join().unwrap(); thread2.join().unwrap(); thread3.join().unwrap(); diff --git a/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.rs b/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.rs index 7f5ec477e19..1c6c2f70c1d 100644 --- a/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.rs +++ b/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.rs @@ -5,7 +5,6 @@ //@error-in-other-file: deadlock use std::convert::TryInto; -use std::thread; use std::thread::spawn; // Using `as` cast since `EPOLLET` wraps around @@ -41,10 +40,10 @@ fn check_epoll_wait( // Test if only one thread is unblocked if multiple threads blocked on same epfd. // Expected execution: -// 1. Thread 2 blocks. -// 2. Thread 3 blocks. -// 3. Thread 1 unblocks thread 3. -// 4. Thread 2 deadlocks. +// 1. Thread 1 blocks. +// 2. Thread 2 blocks. +// 3. Thread 3 unblocks thread 2. +// 4. Thread 1 deadlocks. fn main() { // Create an epoll instance. let epfd = unsafe { libc::epoll_create1(0) }; @@ -65,30 +64,21 @@ fn main() { let expected_value = fds[0] as u64; check_epoll_wait::<1>(epfd, &[(expected_event, expected_value)], 0); - let thread1 = spawn(move || { - thread::park(); - let data = "abcde".as_bytes().as_ptr(); - let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5) }; - assert_eq!(res, 5); - }); - let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap(); let expected_value = fds[0] as u64; - let thread2 = spawn(move || { - thread::park(); + let thread1 = spawn(move || { check_epoll_wait::<1>(epfd, &[(expected_event, expected_value)], -1); //~^ERROR: deadlocked }); - let thread3 = spawn(move || { - thread::park(); + let thread2 = spawn(move || { check_epoll_wait::<1>(epfd, &[(expected_event, expected_value)], -1); }); - thread2.thread().unpark(); - thread::yield_now(); - thread3.thread().unpark(); - thread::yield_now(); - thread1.thread().unpark(); + let thread3 = spawn(move || { + let data = "abcde".as_bytes().as_ptr(); + let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5) }; + assert_eq!(res, 5); + }); thread1.join().unwrap(); thread2.join().unwrap(); diff --git a/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.stderr b/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.stderr index 010dabc1364..b29794f68dd 100644 --- a/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.stderr +++ b/src/tools/miri/tests/fail-dep/libc/libc_epoll_block_two_thread.stderr @@ -1,3 +1,9 @@ +error: deadlock: the evaluated program deadlocked + | + = note: the evaluated program deadlocked + = note: (no span available) + = note: BACKTRACE on thread `unnamed-ID`: + error: deadlock: the evaluated program deadlocked --> RUSTLIB/std/src/sys/pal/PLATFORM/thread.rs:LL:CC | @@ -11,15 +17,9 @@ LL | let ret = unsafe { libc::pthread_join(id, ptr::null_mut()) }; note: inside `main` --> tests/fail-dep/libc/libc_epoll_block_two_thread.rs:LL:CC | -LL | thread2.join().unwrap(); +LL | thread1.join().unwrap(); | ^^^^^^^^^^^^^^ -error: deadlock: the evaluated program deadlocked - | - = note: the evaluated program deadlocked - = note: (no span available) - = note: BACKTRACE on thread `unnamed-ID`: - error: deadlock: the evaluated program deadlocked --> tests/fail-dep/libc/libc_epoll_block_two_thread.rs:LL:CC | diff --git a/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs b/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs index dd9c0eb0b54..dfb8f030dbe 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs @@ -197,7 +197,6 @@ fn test_two_threads_blocked_on_eventfd() { assert_eq!(res, 8); let thread1 = thread::spawn(move || { - thread::park(); let sized_8_data = 1_u64.to_ne_bytes(); let res: i64 = unsafe { libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap() @@ -207,7 +206,6 @@ fn test_two_threads_blocked_on_eventfd() { }); let thread2 = thread::spawn(move || { - thread::park(); let sized_8_data = 1_u64.to_ne_bytes(); let res: i64 = unsafe { libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap() @@ -217,7 +215,6 @@ fn test_two_threads_blocked_on_eventfd() { }); let thread3 = thread::spawn(move || { - thread::park(); let mut buf: [u8; 8] = [0; 8]; // This will unblock previously blocked eventfd read. let res = read_bytes(fd, &mut buf); @@ -227,10 +224,6 @@ fn test_two_threads_blocked_on_eventfd() { assert_eq!(counter, (u64::MAX - 1)); }); - thread1.thread().unpark(); - thread2.thread().unpark(); - thread3.thread().unpark(); - thread1.join().unwrap(); thread2.join().unwrap(); thread3.join().unwrap(); -- cgit 1.4.1-3-g733a5 From 15001f36d115b2b8017c2d25211c2feec56d2752 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 12 Nov 2024 21:52:57 +0000 Subject: filesystem support for solarish. close #3890 --- src/tools/miri/ci/ci.sh | 4 +- .../miri/src/shims/unix/freebsd/foreign_items.rs | 6 +- src/tools/miri/src/shims/unix/fs.rs | 66 ++++++++++++++-------- .../miri/src/shims/unix/macos/foreign_items.rs | 6 +- .../miri/src/shims/unix/solarish/foreign_items.rs | 20 +++++++ src/tools/miri/tests/pass/shims/fs.rs | 7 ++- 6 files changed, 75 insertions(+), 34 deletions(-) (limited to 'src/tools') diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index 1e5a2847c6f..8e6e31bee43 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -152,8 +152,8 @@ case $HOST_TARGET in UNIX="hello panic/panic panic/unwind concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe - TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe - TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe + TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe fs + TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe fs TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random sync threadname pthread epoll eventfd TEST_TARGET=wasm32-wasip2 run_tests_minimal $BASIC wasm TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std empty_main wasm # this target doesn't really have std diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index 1346d8de7ea..0c9bc005ece 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -53,19 +53,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "stat" | "stat@FBSD_1.0" => { let [path, buf] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - let result = this.macos_fbsd_stat(path, buf)?; + let result = this.macos_fbsd_solaris_stat(path, buf)?; this.write_scalar(result, dest)?; } "lstat" | "lstat@FBSD_1.0" => { let [path, buf] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - let result = this.macos_fbsd_lstat(path, buf)?; + let result = this.macos_fbsd_solaris_lstat(path, buf)?; this.write_scalar(result, dest)?; } "fstat" | "fstat@FBSD_1.0" => { let [fd, buf] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - let result = this.macos_fbsd_fstat(fd, buf)?; + let result = this.macos_fbsd_solaris_fstat(fd, buf)?; this.write_scalar(result, dest)?; } "readdir_r" | "readdir_r@FBSD_1.0" => { diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 091def7ac65..070fdc94695 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -265,47 +265,59 @@ impl FileDescription for FileHandle { impl<'tcx> EvalContextExtPrivate<'tcx> for crate::MiriInterpCx<'tcx> {} trait EvalContextExtPrivate<'tcx>: crate::MiriInterpCxExt<'tcx> { - fn macos_stat_write_buf( + fn macos_fbsd_solaris_write_buf( &mut self, metadata: FileMetadata, buf_op: &OpTy<'tcx>, ) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); - let mode: u16 = metadata.mode.to_u16()?; - let (access_sec, access_nsec) = metadata.accessed.unwrap_or((0, 0)); let (created_sec, created_nsec) = metadata.created.unwrap_or((0, 0)); let (modified_sec, modified_nsec) = metadata.modified.unwrap_or((0, 0)); + let mode = metadata.mode.to_uint(this.libc_ty_layout("mode_t").size)?; let buf = this.deref_pointer_as(buf_op, this.libc_ty_layout("stat"))?; - this.write_int_fields_named( &[ ("st_dev", 0), - ("st_mode", mode.into()), + ("st_mode", mode.try_into().unwrap()), ("st_nlink", 0), ("st_ino", 0), ("st_uid", 0), ("st_gid", 0), ("st_rdev", 0), ("st_atime", access_sec.into()), - ("st_atime_nsec", access_nsec.into()), ("st_mtime", modified_sec.into()), - ("st_mtime_nsec", modified_nsec.into()), ("st_ctime", 0), - ("st_ctime_nsec", 0), - ("st_birthtime", created_sec.into()), - ("st_birthtime_nsec", created_nsec.into()), ("st_size", metadata.size.into()), ("st_blocks", 0), ("st_blksize", 0), - ("st_flags", 0), - ("st_gen", 0), ], &buf, )?; + if matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") { + this.write_int_fields_named( + &[ + ("st_atime_nsec", access_nsec.into()), + ("st_mtime_nsec", modified_nsec.into()), + ("st_ctime_nsec", 0), + ("st_birthtime", created_sec.into()), + ("st_birthtime_nsec", created_nsec.into()), + ("st_flags", 0), + ("st_gen", 0), + ], + &buf, + )?; + } + + if matches!(&*this.tcx.sess.target.os, "solaris" | "illumos") { + // FIXME: write st_fstype field once libc is updated. + // https://github.com/rust-lang/libc/pull/4145 + //this.write_int_fields_named(&[("st_fstype", 0)], &buf)?; + } + interp_ok(0) } @@ -648,15 +660,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) } - fn macos_fbsd_stat( + fn macos_fbsd_solaris_stat( &mut self, path_op: &OpTy<'tcx>, buf_op: &OpTy<'tcx>, ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") { - panic!("`macos_fbsd_stat` should not be called on {}", this.tcx.sess.target.os); + if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd" | "solaris" | "illumos") { + panic!("`macos_fbsd_solaris_stat` should not be called on {}", this.tcx.sess.target.os); } let path_scalar = this.read_pointer(path_op)?; @@ -674,19 +686,22 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Err(err) => return this.set_last_error_and_return_i32(err), }; - interp_ok(Scalar::from_i32(this.macos_stat_write_buf(metadata, buf_op)?)) + interp_ok(Scalar::from_i32(this.macos_fbsd_solaris_write_buf(metadata, buf_op)?)) } // `lstat` is used to get symlink metadata. - fn macos_fbsd_lstat( + fn macos_fbsd_solaris_lstat( &mut self, path_op: &OpTy<'tcx>, buf_op: &OpTy<'tcx>, ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") { - panic!("`macos_fbsd_lstat` should not be called on {}", this.tcx.sess.target.os); + if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd" | "solaris" | "illumos") { + panic!( + "`macos_fbsd_solaris_lstat` should not be called on {}", + this.tcx.sess.target.os + ); } let path_scalar = this.read_pointer(path_op)?; @@ -703,18 +718,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Err(err) => return this.set_last_error_and_return_i32(err), }; - interp_ok(Scalar::from_i32(this.macos_stat_write_buf(metadata, buf_op)?)) + interp_ok(Scalar::from_i32(this.macos_fbsd_solaris_write_buf(metadata, buf_op)?)) } - fn macos_fbsd_fstat( + fn macos_fbsd_solaris_fstat( &mut self, fd_op: &OpTy<'tcx>, buf_op: &OpTy<'tcx>, ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") { - panic!("`macos_fbsd_fstat` should not be called on {}", this.tcx.sess.target.os); + if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd" | "solaris" | "illumos") { + panic!( + "`macos_fbsd_solaris_fstat` should not be called on {}", + this.tcx.sess.target.os + ); } let fd = this.read_scalar(fd_op)?.to_i32()?; @@ -730,7 +748,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(metadata) => metadata, Err(err) => return this.set_last_error_and_return_i32(err), }; - interp_ok(Scalar::from_i32(this.macos_stat_write_buf(metadata, buf_op)?)) + interp_ok(Scalar::from_i32(this.macos_fbsd_solaris_write_buf(metadata, buf_op)?)) } fn linux_statx( diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index 003025916cd..103bea08620 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -40,19 +40,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "stat" | "stat64" | "stat$INODE64" => { let [path, buf] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - let result = this.macos_fbsd_stat(path, buf)?; + let result = this.macos_fbsd_solaris_stat(path, buf)?; this.write_scalar(result, dest)?; } "lstat" | "lstat64" | "lstat$INODE64" => { let [path, buf] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - let result = this.macos_fbsd_lstat(path, buf)?; + let result = this.macos_fbsd_solaris_lstat(path, buf)?; this.write_scalar(result, dest)?; } "fstat" | "fstat64" | "fstat$INODE64" => { let [fd, buf] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - let result = this.macos_fbsd_fstat(fd, buf)?; + let result = this.macos_fbsd_solaris_fstat(fd, buf)?; this.write_scalar(result, dest)?; } "opendir$INODE64" => { diff --git a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs index 1bbd25617e5..e4529170368 100644 --- a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs @@ -57,6 +57,26 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } + // File related shims + "stat" | "stat64" => { + let [path, buf] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.macos_fbsd_solaris_stat(path, buf)?; + this.write_scalar(result, dest)?; + } + "lstat" | "lstat64" => { + let [path, buf] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.macos_fbsd_solaris_lstat(path, buf)?; + this.write_scalar(result, dest)?; + } + "fstat" | "fstat64" => { + let [fd, buf] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.macos_fbsd_solaris_fstat(fd, buf)?; + this.write_scalar(result, dest)?; + } + // Miscellaneous "___errno" => { let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs index 81151f4ac47..3e514d95ee9 100644 --- a/src/tools/miri/tests/pass/shims/fs.rs +++ b/src/tools/miri/tests/pass/shims/fs.rs @@ -27,8 +27,11 @@ fn main() { test_file_sync(); test_errors(); test_rename(); - test_directory(); - test_canonicalize(); + // solarish needs to support readdir/readdir64 for these tests. + if cfg!(not(any(target_os = "solaris", target_os = "illumos"))) { + test_directory(); + test_canonicalize(); + } test_from_raw_os_error(); #[cfg(unix)] test_pread_pwrite(); -- cgit 1.4.1-3-g733a5 From f592dd95dbfc892c1153af67e0ab5b4e593d33e7 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 24 Nov 2024 09:08:07 -0800 Subject: Compiletest: Add proc-macro header This adds a proc-macro header to make it easier to depend on a proc-macro, and remove some of the boilerplate necessary. --- src/tools/compiletest/src/directive-list.rs | 1 + src/tools/compiletest/src/header.rs | 1 + src/tools/compiletest/src/header/auxiliary.rs | 11 ++-- src/tools/compiletest/src/runtest.rs | 76 ++++++++++++++++++++------- 4 files changed, 66 insertions(+), 23 deletions(-) (limited to 'src/tools') diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index 0c47ef871d2..952533e904c 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -215,6 +215,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "pp-exact", "pretty-compare-only", "pretty-mode", + "proc-macro", "reference", "regex-error-pattern", "remap-src-base", diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index e945797647e..fe4c5fdd8b5 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -221,6 +221,7 @@ mod directives { pub const AUX_BIN: &'static str = "aux-bin"; pub const AUX_BUILD: &'static str = "aux-build"; pub const AUX_CRATE: &'static str = "aux-crate"; + pub const PROC_MACRO: &'static str = "proc-macro"; pub const AUX_CODEGEN_BACKEND: &'static str = "aux-codegen-backend"; pub const EXEC_ENV: &'static str = "exec-env"; pub const RUSTC_ENV: &'static str = "rustc-env"; diff --git a/src/tools/compiletest/src/header/auxiliary.rs b/src/tools/compiletest/src/header/auxiliary.rs index 6f6538ce196..0e1f3a785f8 100644 --- a/src/tools/compiletest/src/header/auxiliary.rs +++ b/src/tools/compiletest/src/header/auxiliary.rs @@ -4,7 +4,7 @@ use std::iter; use crate::common::Config; -use crate::header::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE}; +use crate::header::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE, PROC_MACRO}; /// Properties parsed from `aux-*` test directives. #[derive(Clone, Debug, Default)] @@ -17,6 +17,8 @@ pub(crate) struct AuxProps { /// Similar to `builds`, but a list of NAME=somelib.rs of dependencies /// to build and pass with the `--extern` flag. pub(crate) crates: Vec<(String, String)>, + /// Same as `builds`, but for proc-macros. + pub(crate) proc_macros: Vec, /// Similar to `builds`, but also uses the resulting dylib as a /// `-Zcodegen-backend` when compiling the test file. pub(crate) codegen_backend: Option, @@ -26,12 +28,13 @@ impl AuxProps { /// Yields all of the paths (relative to `./auxiliary/`) that have been /// specified in `aux-*` directives for this test. pub(crate) fn all_aux_path_strings(&self) -> impl Iterator { - let Self { builds, bins, crates, codegen_backend } = self; + let Self { builds, bins, crates, proc_macros, codegen_backend } = self; iter::empty() .chain(builds.iter().map(String::as_str)) .chain(bins.iter().map(String::as_str)) .chain(crates.iter().map(|(_, path)| path.as_str())) + .chain(proc_macros.iter().map(String::as_str)) .chain(codegen_backend.iter().map(String::as_str)) } } @@ -39,13 +42,15 @@ impl AuxProps { /// If the given test directive line contains an `aux-*` directive, parse it /// and update [`AuxProps`] accordingly. pub(super) fn parse_and_update_aux(config: &Config, ln: &str, aux: &mut AuxProps) { - if !ln.starts_with("aux-") { + if !(ln.starts_with("aux-") || ln.starts_with("proc-macro")) { return; } config.push_name_value_directive(ln, AUX_BUILD, &mut aux.builds, |r| r.trim().to_string()); config.push_name_value_directive(ln, AUX_BIN, &mut aux.bins, |r| r.trim().to_string()); config.push_name_value_directive(ln, AUX_CRATE, &mut aux.crates, parse_aux_crate); + config + .push_name_value_directive(ln, PROC_MACRO, &mut aux.proc_macros, |r| r.trim().to_string()); if let Some(r) = config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND) { aux.codegen_backend = Some(r.trim().to_owned()); } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index bc80c8246ad..93e5980f1f5 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -102,7 +102,7 @@ fn get_lib_name(name: &str, aux_type: AuxType) -> Option { // In this case, the only path we can pass // with '--extern-meta' is the '.rlib' file AuxType::Lib => Some(format!("lib{name}.rlib")), - AuxType::Dylib => Some(dylib_name(name)), + AuxType::Dylib | AuxType::ProcMacro => Some(dylib_name(name)), } } @@ -1097,7 +1097,9 @@ impl<'test> TestCx<'test> { } fn has_aux_dir(&self) -> bool { - !self.props.aux.builds.is_empty() || !self.props.aux.crates.is_empty() + !self.props.aux.builds.is_empty() + || !self.props.aux.crates.is_empty() + || !self.props.aux.proc_macros.is_empty() } fn aux_output_dir(&self) -> PathBuf { @@ -1118,31 +1120,48 @@ impl<'test> TestCx<'test> { fn build_all_auxiliary(&self, of: &TestPaths, aux_dir: &Path, rustc: &mut Command) { for rel_ab in &self.props.aux.builds { - self.build_auxiliary(of, rel_ab, &aux_dir, false /* is_bin */); + self.build_auxiliary(of, rel_ab, &aux_dir, None); } for rel_ab in &self.props.aux.bins { - self.build_auxiliary(of, rel_ab, &aux_dir, true /* is_bin */); + self.build_auxiliary(of, rel_ab, &aux_dir, Some(AuxType::Bin)); } + let path_to_crate_name = |path: &str| -> String { + path.rsplit_once('/') + .map_or(path, |(_, tail)| tail) + .trim_end_matches(".rs") + .replace('-', "_") + }; + + let add_extern = + |rustc: &mut Command, aux_name: &str, aux_path: &str, aux_type: AuxType| { + let lib_name = get_lib_name(&path_to_crate_name(aux_path), aux_type); + if let Some(lib_name) = lib_name { + rustc.arg("--extern").arg(format!( + "{}={}/{}", + aux_name, + aux_dir.display(), + lib_name + )); + } + }; + for (aux_name, aux_path) in &self.props.aux.crates { - let aux_type = self.build_auxiliary(of, &aux_path, &aux_dir, false /* is_bin */); - let lib_name = - get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"), aux_type); - if let Some(lib_name) = lib_name { - rustc.arg("--extern").arg(format!( - "{}={}/{}", - aux_name, - aux_dir.display(), - lib_name - )); - } + let aux_type = self.build_auxiliary(of, &aux_path, &aux_dir, None); + add_extern(rustc, aux_name, aux_path, aux_type); + } + + for proc_macro in &self.props.aux.proc_macros { + self.build_auxiliary(of, proc_macro, &aux_dir, Some(AuxType::ProcMacro)); + let crate_name = path_to_crate_name(proc_macro); + add_extern(rustc, &crate_name, proc_macro, AuxType::ProcMacro); } // Build any `//@ aux-codegen-backend`, and pass the resulting library // to `-Zcodegen-backend` when compiling the test file. if let Some(aux_file) = &self.props.aux.codegen_backend { - let aux_type = self.build_auxiliary(of, aux_file, aux_dir, false); + let aux_type = self.build_auxiliary(of, aux_file, aux_dir, None); if let Some(lib_name) = get_lib_name(aux_file.trim_end_matches(".rs"), aux_type) { let lib_path = aux_dir.join(&lib_name); rustc.arg(format!("-Zcodegen-backend={}", lib_path.display())); @@ -1209,17 +1228,23 @@ impl<'test> TestCx<'test> { } /// Builds an aux dependency. + /// + /// If `aux_type` is `None`, then this will determine the aux-type automatically. fn build_auxiliary( &self, of: &TestPaths, source_path: &str, aux_dir: &Path, - is_bin: bool, + aux_type: Option, ) -> AuxType { let aux_testpaths = self.compute_aux_test_paths(of, source_path); - let aux_props = self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config); + let mut aux_props = + self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config); + if aux_type == Some(AuxType::ProcMacro) { + aux_props.force_host = true; + } let mut aux_dir = aux_dir.to_path_buf(); - if is_bin { + if aux_type == Some(AuxType::Bin) { // On unix, the binary of `auxiliary/foo.rs` will be named // `auxiliary/foo` which clashes with the _dir_ `auxiliary/foo`, so // put bins in a `bin` subfolder. @@ -1250,8 +1275,12 @@ impl<'test> TestCx<'test> { aux_rustc.env_remove(key); } - let (aux_type, crate_type) = if is_bin { + let (aux_type, crate_type) = if aux_type == Some(AuxType::Bin) { (AuxType::Bin, Some("bin")) + } else if aux_type == Some(AuxType::ProcMacro) { + (AuxType::ProcMacro, Some("proc-macro")) + } else if aux_type.is_some() { + panic!("aux_type {aux_type:?} not expected"); } else if aux_props.no_prefer_dynamic { (AuxType::Dylib, None) } else if self.config.target.contains("emscripten") @@ -1287,6 +1316,11 @@ impl<'test> TestCx<'test> { aux_rustc.args(&["--crate-type", crate_type]); } + if aux_type == AuxType::ProcMacro { + // For convenience, but this only works on 2018. + aux_rustc.args(&["--extern", "proc_macro"]); + } + aux_rustc.arg("-L").arg(&aux_dir); let auxres = aux_cx.compose_and_run( @@ -2768,8 +2802,10 @@ enum LinkToAux { No, } +#[derive(Debug, PartialEq)] enum AuxType { Bin, Lib, Dylib, + ProcMacro, } -- cgit 1.4.1-3-g733a5 From 22998f078588cf479530ff93e4a66ab4bb666398 Mon Sep 17 00:00:00 2001 From: Boxy Date: Wed, 27 Nov 2024 15:14:47 +0000 Subject: update cfgs --- compiler/rustc_builtin_macros/src/lib.rs | 2 +- library/alloc/benches/lib.rs | 3 +- library/alloc/src/boxed.rs | 11 +- library/alloc/src/lib.rs | 3 +- library/alloc/src/raw_vec.rs | 3 - library/alloc/src/rc.rs | 2 +- library/alloc/src/sync.rs | 2 +- library/alloc/src/vec/mod.rs | 4 +- library/alloc/tests/boxed.rs | 2 +- library/alloc/tests/lib.rs | 3 +- library/core/Cargo.toml | 2 - library/core/src/alloc/layout.rs | 9 +- library/core/src/cell.rs | 9 +- library/core/src/char/methods.rs | 5 - library/core/src/ffi/c_str.rs | 8 +- library/core/src/fmt/mod.rs | 4 - library/core/src/future/future.rs | 2 +- library/core/src/hint.rs | 1 - library/core/src/intrinsics/mod.rs | 246 +++++---------------- library/core/src/lib.rs | 7 +- library/core/src/macros/mod.rs | 1 - library/core/src/mem/maybe_uninit.rs | 9 +- library/core/src/num/int_macros.rs | 7 - library/core/src/num/mod.rs | 1 - library/core/src/num/uint_macros.rs | 7 - library/core/src/ops/deref.rs | 6 +- library/core/src/ops/mod.rs | 1 - library/core/src/option.rs | 2 +- library/core/src/panic.rs | 3 +- library/core/src/panicking.rs | 27 +-- library/core/src/ptr/alignment.rs | 7 - library/core/src/ptr/const_ptr.rs | 2 - library/core/src/ptr/metadata.rs | 3 - library/core/src/ptr/mut_ptr.rs | 2 - library/core/src/ptr/non_null.rs | 1 - library/core/src/result.rs | 2 +- library/core/src/slice/memchr.rs | 4 - library/core/src/slice/mod.rs | 4 +- library/core/src/str/mod.rs | 4 +- library/core/src/task/wake.rs | 2 - library/core/src/ub_checks.rs | 2 - library/core/src/unicode/unicode_data.rs | 3 - library/core/tests/lib.rs | 4 +- library/panic_unwind/Cargo.toml | 5 +- library/std/Cargo.toml | 2 - library/std/src/lib.rs | 6 +- library/std/src/sys/sync/condvar/no_threads.rs | 1 - library/std/src/sys/sync/mutex/no_threads.rs | 1 - library/std/src/sys/sync/once/no_threads.rs | 1 - library/std/src/sys/sync/once/queue.rs | 1 - library/std/src/sys/sync/rwlock/no_threads.rs | 1 - library/std/src/sys/thread_local/key/racy.rs | 1 - library/std/src/sys/thread_local/os.rs | 1 - library/std/src/thread/local.rs | 1 - library/unwind/Cargo.toml | 5 +- .../unicode-table-generator/src/range_search.rs | 1 - .../unicode-table-generator/src/raw_emitter.rs | 4 - 57 files changed, 107 insertions(+), 356 deletions(-) (limited to 'src/tools') diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 9eee92164cf..cc4a974e757 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -5,10 +5,10 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(not(bootstrap), feature(autodiff))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] +#![feature(autodiff)] #![feature(box_patterns)] #![feature(decl_macro)] #![feature(if_let_guard)] diff --git a/library/alloc/benches/lib.rs b/library/alloc/benches/lib.rs index c1907361f93..2633154318c 100644 --- a/library/alloc/benches/lib.rs +++ b/library/alloc/benches/lib.rs @@ -4,8 +4,7 @@ #![feature(iter_next_chunk)] #![feature(repr_simd)] #![feature(slice_partition_dedup)] -#![cfg_attr(bootstrap, feature(strict_provenance))] -#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] +#![feature(strict_provenance_lints)] #![feature(test)] #![deny(fuzzy_provenance_casts)] diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index ee60ec0fbac..e0f94428cfa 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -191,9 +191,7 @@ use core::error::{self, Error}; use core::fmt; use core::future::Future; use core::hash::{Hash, Hasher}; -#[cfg(not(bootstrap))] -use core::marker::PointerLike; -use core::marker::{Tuple, Unsize}; +use core::marker::{PointerLike, Tuple, Unsize}; use core::mem::{self, SizedTypeProperties}; use core::ops::{ AsyncFn, AsyncFnMut, AsyncFnOnce, CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut, @@ -227,7 +225,7 @@ pub use thin::ThinBox; #[fundamental] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_insignificant_dtor] -#[cfg_attr(not(bootstrap), doc(search_unbox))] +#[doc(search_unbox)] // The declaration of the `Box` struct must be kept in sync with the // compiler or ICEs will happen. pub struct Box< @@ -1502,7 +1500,7 @@ impl Box { /// [`as_ptr`]: Self::as_ptr #[unstable(feature = "box_as_ptr", issue = "129090")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline] pub fn as_mut_ptr(b: &mut Self) -> *mut T { // This is a primitive deref, not going through `DerefMut`, and therefore not materializing @@ -1551,7 +1549,7 @@ impl Box { /// [`as_ptr`]: Self::as_ptr #[unstable(feature = "box_as_ptr", issue = "129090")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline] pub fn as_ptr(b: &Self) -> *const T { // This is a primitive deref, not going through `DerefMut`, and therefore not materializing @@ -2134,6 +2132,5 @@ impl Error for Box { } } -#[cfg(not(bootstrap))] #[unstable(feature = "pointer_like_trait", issue = "none")] impl PointerLike for Box {} diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 041ff37897f..108224b27fa 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -163,8 +163,6 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(strict_provenance))] -#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] #![cfg_attr(not(test), feature(coroutine_trait))] #![cfg_attr(test, feature(panic_update_hook))] #![cfg_attr(test, feature(test))] @@ -188,6 +186,7 @@ #![feature(slice_internals)] #![feature(staged_api)] #![feature(stmt_expr_attributes)] +#![feature(strict_provenance_lints)] #![feature(unboxed_closures)] #![feature(unsized_fn_params)] #![feature(with_negative_coherence)] diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 85a9120c7e2..48429aea16b 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -103,7 +103,6 @@ impl RawVec { /// `RawVec` with capacity `usize::MAX`. Useful for implementing /// delayed allocation. #[must_use] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81"))] pub const fn new() -> Self { Self::new_in(Global) } @@ -179,7 +178,6 @@ impl RawVec { /// Like `new`, but parameterized over the choice of allocator for /// the returned `RawVec`. #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81"))] pub const fn new_in(alloc: A) -> Self { Self { inner: RawVecInner::new_in(alloc, align_of::()), _marker: PhantomData } } @@ -409,7 +407,6 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec { impl RawVecInner { #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81"))] const fn new_in(alloc: A, align: usize) -> Self { let ptr = unsafe { core::mem::transmute(align) }; // `cap: 0` means "unallocated". zero-sized types are ignored. diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 48ffdcb77d3..7aa1457b1df 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -307,7 +307,7 @@ fn rc_inner_layout_for_value_layout(layout: Layout) -> Layout { /// `value.get_mut()`. This avoids conflicts with methods of the inner type `T`. /// /// [get_mut]: Rc::get_mut -#[cfg_attr(not(bootstrap), doc(search_unbox))] +#[doc(search_unbox)] #[cfg_attr(not(test), rustc_diagnostic_item = "Rc")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_insignificant_dtor] diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index f7d1c9e4efb..b8bdd298c27 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -235,7 +235,7 @@ macro_rules! acquire { /// counting in general. /// /// [rc_examples]: crate::rc#examples -#[cfg_attr(not(bootstrap), doc(search_unbox))] +#[doc(search_unbox)] #[cfg_attr(not(test), rustc_diagnostic_item = "Arc")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_insignificant_dtor] diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 990b7e8f761..4750d663e0c 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1662,7 +1662,7 @@ impl Vec { #[stable(feature = "vec_as_ptr", since = "1.37.0")] #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline] pub const fn as_ptr(&self) -> *const T { // We shadow the slice method of the same name to avoid going through @@ -1725,7 +1725,7 @@ impl Vec { #[stable(feature = "vec_as_ptr", since = "1.37.0")] #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline] pub const fn as_mut_ptr(&mut self) -> *mut T { // We shadow the slice method of the same name to avoid going through diff --git a/library/alloc/tests/boxed.rs b/library/alloc/tests/boxed.rs index 6a8ba5c92fb..94389cf2de9 100644 --- a/library/alloc/tests/boxed.rs +++ b/library/alloc/tests/boxed.rs @@ -4,7 +4,7 @@ use core::mem::MaybeUninit; use core::ptr::NonNull; #[test] -#[cfg_attr(not(bootstrap), expect(dangling_pointers_from_temporaries))] +#[expect(dangling_pointers_from_temporaries)] fn uninitialized_zero_size_box() { assert_eq!( &*Box::<()>::new_uninit() as *const _, diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 699a8e6776e..02bbb40ef81 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -32,10 +32,9 @@ #![feature(panic_update_hook)] #![feature(pointer_is_aligned_to)] #![feature(thin_box)] -#![cfg_attr(bootstrap, feature(strict_provenance))] -#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] #![feature(drain_keep_rest)] #![feature(local_waker)] +#![feature(strict_provenance_lints)] #![feature(vec_pop_if)] #![feature(unique_rc_arc)] #![feature(macro_metavar_expr_concat)] diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml index 94f343d0670..cace4582b48 100644 --- a/library/core/Cargo.toml +++ b/library/core/Cargo.toml @@ -43,8 +43,6 @@ check-cfg = [ 'cfg(bootstrap)', 'cfg(no_fp_fmt_parse)', 'cfg(stdarch_intel_sde)', - # #[cfg(bootstrap)] rtems - 'cfg(target_os, values("rtems"))', # core use #[path] imports to portable-simd `core_simd` crate # and to stdarch `core_arch` crate which messes-up with Cargo list # of declared features, we therefor expect any feature cfg diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index f412ca17163..60936da2e0b 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -157,7 +157,6 @@ impl Layout { #[must_use = "this returns the minimum alignment, \ without modifying the layout"] #[inline] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(ptr_alignment_type))] pub const fn align(&self) -> usize { self.align.as_usize() } @@ -255,7 +254,7 @@ impl Layout { /// `align` violates the conditions listed in [`Layout::from_size_align`]. #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] + #[rustc_const_stable_indirect] #[inline] pub const fn align_to(&self, align: usize) -> Result { if let Some(align) = Alignment::new(align) { @@ -331,7 +330,7 @@ impl Layout { /// to the layout's current size. #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] + #[rustc_const_stable_indirect] #[must_use = "this returns a new `Layout`, \ without modifying the original"] #[inline] @@ -431,7 +430,7 @@ impl Layout { /// ``` #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] + #[rustc_const_stable_indirect] #[inline] pub const fn extend(&self, next: Self) -> Result<(Self, usize), LayoutError> { let new_align = Alignment::max(self.align, next.align); @@ -495,7 +494,7 @@ impl Layout { /// `isize::MAX`, returns `LayoutError`. #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] + #[rustc_const_stable_indirect] #[inline] pub const fn array(n: usize) -> Result { // Reduce the amount of code we need to monomorphize per `T`. diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index d62cb28fc57..c5539790327 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -587,7 +587,7 @@ impl Cell { #[inline] #[stable(feature = "cell_as_ptr", since = "1.12.0")] #[rustc_const_stable(feature = "const_cell_as_ptr", since = "1.32.0")] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[rustc_never_returns_null_ptr] pub const fn as_ptr(&self) -> *mut T { self.value.get() @@ -1150,7 +1150,7 @@ impl RefCell { /// ``` #[inline] #[stable(feature = "cell_as_ptr", since = "1.12.0")] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[rustc_never_returns_null_ptr] pub fn as_ptr(&self) -> *mut T { self.value.get() @@ -2135,7 +2135,6 @@ impl UnsafeCell { #[inline(always)] #[stable(feature = "unsafe_cell_from_mut", since = "1.84.0")] #[rustc_const_stable(feature = "unsafe_cell_from_mut", since = "1.84.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn from_mut(value: &mut T) -> &mut UnsafeCell { // SAFETY: `UnsafeCell` has the same memory layout as `T` due to #[repr(transparent)]. unsafe { &mut *(value as *mut T as *mut UnsafeCell) } @@ -2160,7 +2159,7 @@ impl UnsafeCell { #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_unsafecell_get", since = "1.32.0")] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[rustc_never_returns_null_ptr] pub const fn get(&self) -> *mut T { // We can just cast the pointer from `UnsafeCell` to `T` because of @@ -2308,7 +2307,7 @@ impl SyncUnsafeCell { /// when casting to `&mut T`, and ensure that there are no mutations /// or mutable aliases going on when casting to `&T` #[inline] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[rustc_never_returns_null_ptr] pub const fn get(&self) -> *mut T { self.value.get() diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 86822af31ca..7d33765879f 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -1787,7 +1787,6 @@ const fn len_utf16(code: u32) -> usize { /// Panics if the buffer is not large enough. /// A buffer of length four is large enough to encode any `char`. #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_char_encode_utf8", since = "1.83.0"))] #[doc(hidden)] #[inline] pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] { @@ -1836,10 +1835,6 @@ pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] { /// Panics if the buffer is not large enough. /// A buffer of length 2 is large enough to encode any `char`. #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_char_encode_utf16", since = "1.84.0") -)] #[doc(hidden)] #[inline] pub const fn encode_utf16_raw(mut code: u32, dst: &mut [u16]) -> &mut [u16] { diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 9e32f74227c..8831443a10f 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -138,11 +138,9 @@ enum FromBytesWithNulErrorKind { // FIXME: const stability attributes should not be required here, I think impl FromBytesWithNulError { - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0"))] const fn interior_nul(pos: usize) -> FromBytesWithNulError { FromBytesWithNulError { kind: FromBytesWithNulErrorKind::InteriorNul(pos) } } - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0"))] const fn not_nul_terminated() -> FromBytesWithNulError { FromBytesWithNulError { kind: FromBytesWithNulErrorKind::NotNulTerminated } } @@ -464,8 +462,7 @@ impl CStr { /// /// ```no_run /// # #![allow(unused_must_use)] - /// # #![cfg_attr(bootstrap, expect(temporary_cstring_as_ptr))] - /// # #![cfg_attr(not(bootstrap), expect(dangling_pointers_from_temporaries))] + /// # #![expect(dangling_pointers_from_temporaries)] /// use std::ffi::CString; /// /// // Do not do this: @@ -500,7 +497,7 @@ impl CStr { #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_str_as_ptr", since = "1.32.0")] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[rustc_never_returns_null_ptr] pub const fn as_ptr(&self) -> *const c_char { self.inner.as_ptr() @@ -732,7 +729,6 @@ impl AsRef for CStr { /// located within `isize::MAX` from `ptr`. #[inline] #[unstable(feature = "cstr_internals", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0"))] #[rustc_allow_const_fn_unstable(const_eval_select)] const unsafe fn strlen(ptr: *const c_char) -> usize { const_eval_select!( diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 9db6d27967f..7fc9dd21fdd 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -333,10 +333,6 @@ pub struct Arguments<'a> { #[unstable(feature = "fmt_internals", issue = "none")] impl<'a> Arguments<'a> { #[inline] - #[cfg_attr( - bootstrap, - rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none") - )] pub const fn new_const(pieces: &'a [&'static str; N]) -> Self { const { assert!(N <= 1) }; Arguments { pieces, fmt: None, args: &[] } diff --git a/library/core/src/future/future.rs b/library/core/src/future/future.rs index 234914c20fc..cfbd88bbe79 100644 --- a/library/core/src/future/future.rs +++ b/library/core/src/future/future.rs @@ -25,7 +25,7 @@ use crate::task::{Context, Poll}; /// [`async`]: ../../std/keyword.async.html /// [`Waker`]: crate::task::Waker #[doc(notable_trait)] -#[cfg_attr(not(bootstrap), doc(search_unbox))] +#[doc(search_unbox)] #[must_use = "futures do nothing unless you `.await` or poll them"] #[stable(feature = "futures_api", since = "1.36.0")] #[lang = "future_trait"] diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 78df51f2bc4..c59e4414d37 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -506,7 +506,6 @@ pub const fn black_box(dummy: T) -> T { /// # } /// ``` #[unstable(feature = "hint_must_use", issue = "94745")] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "hint_must_use", issue = "94745"))] #[must_use] // <-- :) #[inline(always)] pub const fn must_use(value: T) -> T { diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 8741e1b0807..6b9011adf3d 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -1431,11 +1431,7 @@ pub fn abort() -> ! { /// reach code marked with this function. /// /// The stabilized version of this intrinsic is [`core::hint::unreachable_unchecked`]. -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1453,8 +1449,7 @@ pub const unsafe fn unreachable() -> ! { /// own, or if it does not enable any significant optimizations. /// /// The stabilized version of this intrinsic is [`core::hint::assert_unchecked`]. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assume", since = "1.77.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] @@ -1474,8 +1469,7 @@ pub const unsafe fn assume(b: bool) { /// /// This intrinsic does not have a stable counterpart. #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(not(bootstrap), rustc_intrinsic)] -#[cfg(not(bootstrap))] +#[rustc_intrinsic] #[rustc_nounwind] #[miri::intrinsic_fallback_is_spec] #[cold] @@ -1492,19 +1486,10 @@ pub const fn cold_path() {} /// any safety invariants. /// /// This intrinsic does not have a stable counterpart. -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_likely", since = "1.84.0") -)] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_nounwind] #[inline(always)] pub const fn likely(b: bool) -> bool { - #[cfg(bootstrap)] - { - b - } - #[cfg(not(bootstrap))] if b { true } else { @@ -1524,19 +1509,10 @@ pub const fn likely(b: bool) -> bool { /// any safety invariants. /// /// This intrinsic does not have a stable counterpart. -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_likely", since = "1.84.0") -)] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_nounwind] #[inline(always)] pub const fn unlikely(b: bool) -> bool { - #[cfg(bootstrap)] - { - b - } - #[cfg(not(bootstrap))] if b { cold_path(); true @@ -1570,8 +1546,7 @@ pub fn select_unpredictable(b: bool, true_val: T, false_val: T) -> T { /// This will statically either panic, or do nothing. /// /// This intrinsic does not have a stable counterpart. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type", since = "1.59.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1583,8 +1558,7 @@ pub const fn assert_inhabited() { /// zero-initialization: This will statically either panic, or do nothing. /// /// This intrinsic does not have a stable counterpart. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type2", since = "1.75.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1595,8 +1569,7 @@ pub const fn assert_zero_valid() { /// A guard for `std::mem::uninitialized`. This will statically either panic, or do nothing. /// /// This intrinsic does not have a stable counterpart. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type2", since = "1.75.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1612,8 +1585,7 @@ pub const fn assert_mem_uninitialized_valid() { /// any safety invariants. /// /// Consider using [`core::panic::Location::caller`] instead. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_caller_location", since = "1.79.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1630,8 +1602,7 @@ pub const fn caller_location() -> &'static crate::panic::Location<'static> { /// it does not require an `unsafe` block. /// Therefore, implementations must not require the user to uphold /// any safety invariants. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_intrinsic_forget", since = "1.83.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1944,8 +1915,7 @@ pub const unsafe fn transmute(_src: Src) -> Dst { /// /// This is not expected to ever be exposed directly to users, rather it /// may eventually be exposed through some more-constrained API. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_transmute", since = "1.56.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1966,8 +1936,7 @@ pub const unsafe fn transmute_unchecked(_src: Src) -> Dst { /// any safety invariants. /// /// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop). -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_needs_drop", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -1992,8 +1961,7 @@ pub const fn needs_drop() -> bool { /// /// The stabilized version of this intrinsic is [`pointer::offset`]. #[must_use = "returns a new pointer rather than modifying its argument"] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2015,8 +1983,7 @@ pub const unsafe fn offset(_dst: Ptr, _offset: Delta) -> Ptr { /// /// The stabilized version of this intrinsic is [`pointer::wrapping_offset`]. #[must_use = "returns a new pointer rather than modifying its argument"] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2723,8 +2690,7 @@ pub fn frem_algebraic(_a: T, _b: T) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `count_ones` method. For example, /// [`u32::count_ones`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ctpop", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2768,8 +2734,7 @@ pub const fn ctpop(_x: T) -> u32 { /// let num_leading = ctlz(x); /// assert_eq!(num_leading, 16); /// ``` -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ctlz", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2794,8 +2759,7 @@ pub const fn ctlz(_x: T) -> u32 { /// let num_leading = unsafe { ctlz_nonzero(x) }; /// assert_eq!(num_leading, 3); /// ``` -#[cfg_attr(bootstrap, rustc_const_stable(feature = "constctlz", since = "1.50.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2839,8 +2803,7 @@ pub const unsafe fn ctlz_nonzero(_x: T) -> u32 { /// let num_trailing = cttz(x); /// assert_eq!(num_trailing, 16); /// ``` -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cttz", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2865,8 +2828,7 @@ pub const fn cttz(_x: T) -> u32 { /// let num_trailing = unsafe { cttz_nonzero(x) }; /// assert_eq!(num_trailing, 3); /// ``` -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cttz_nonzero", since = "1.53.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2884,8 +2846,7 @@ pub const unsafe fn cttz_nonzero(_x: T) -> u32 { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `swap_bytes` method. For example, /// [`u32::swap_bytes`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_bswap", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2903,8 +2864,7 @@ pub const fn bswap(_x: T) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `reverse_bits` method. For example, /// [`u32::reverse_bits`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_bitreverse", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2919,7 +2879,6 @@ pub const fn bitreverse(_x: T) -> T { /// large and difficult to optimize. /// /// The stabilized version of this intrinsic is [`Ord::cmp`]. -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_three_way_compare", issue = "none"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn three_way_compare(_lhs: T, _rhss: T) -> crate::cmp::Ordering { @@ -2936,8 +2895,7 @@ pub const fn three_way_compare(_lhs: T, _rhss: T) -> crate::cmp::Orderi /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_add` method. For example, /// [`u32::overflowing_add`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2955,8 +2913,7 @@ pub const fn add_with_overflow(_x: T, _y: T) -> (T, bool) { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_sub` method. For example, /// [`u32::overflowing_sub`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2974,8 +2931,7 @@ pub const fn sub_with_overflow(_x: T, _y: T) -> (T, bool) { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_mul` method. For example, /// [`u32::overflowing_mul`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -2987,7 +2943,6 @@ pub const fn mul_with_overflow(_x: T, _y: T) -> (T, bool) { /// `x % y != 0` or `y == 0` or `x == T::MIN && y == -1` /// /// This intrinsic does not have a stable counterpart. -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_exact_div", issue = "none"))] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3001,8 +2956,7 @@ pub const unsafe fn exact_div(_x: T, _y: T) -> T { /// Safe wrappers for this intrinsic are available on the integer /// primitives via the `checked_div` method. For example, /// [`u32::checked_div`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked_div", since = "1.52.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3015,8 +2969,7 @@ pub const unsafe fn unchecked_div(_x: T, _y: T) -> T { /// Safe wrappers for this intrinsic are available on the integer /// primitives via the `checked_rem` method. For example, /// [`u32::checked_rem`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked_rem", since = "1.52.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3030,8 +2983,7 @@ pub const unsafe fn unchecked_rem(_x: T, _y: T) -> T { /// Safe wrappers for this intrinsic are available on the integer /// primitives via the `checked_shl` method. For example, /// [`u32::checked_shl`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3044,8 +2996,7 @@ pub const unsafe fn unchecked_shl(_x: T, _y: U) -> T { /// Safe wrappers for this intrinsic are available on the integer /// primitives via the `checked_shr` method. For example, /// [`u32::checked_shr`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3058,8 +3009,7 @@ pub const unsafe fn unchecked_shr(_x: T, _y: U) -> T { /// /// The stable counterpart of this intrinsic is `unchecked_add` on the various /// integer types, such as [`u16::unchecked_add`] and [`i64::unchecked_add`]. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3072,8 +3022,7 @@ pub const unsafe fn unchecked_add(_x: T, _y: T) -> T { /// /// The stable counterpart of this intrinsic is `unchecked_sub` on the various /// integer types, such as [`u16::unchecked_sub`] and [`i64::unchecked_sub`]. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3086,8 +3035,7 @@ pub const unsafe fn unchecked_sub(_x: T, _y: T) -> T { /// /// The stable counterpart of this intrinsic is `unchecked_mul` on the various /// integer types, such as [`u16::unchecked_mul`] and [`i64::unchecked_mul`]. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3105,8 +3053,7 @@ pub const unsafe fn unchecked_mul(_x: T, _y: T) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `rotate_left` method. For example, /// [`u32::rotate_left`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_rotate", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3124,8 +3071,7 @@ pub const fn rotate_left(_x: T, _shift: u32) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `rotate_right` method. For example, /// [`u32::rotate_right`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_rotate", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3143,8 +3089,7 @@ pub const fn rotate_right(_x: T, _shift: u32) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_add` method. For example, /// [`u32::wrapping_add`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3161,8 +3106,7 @@ pub const fn wrapping_add(_a: T, _b: T) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_sub` method. For example, /// [`u32::wrapping_sub`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3179,8 +3123,7 @@ pub const fn wrapping_sub(_a: T, _b: T) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_mul` method. For example, /// [`u32::wrapping_mul`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3198,8 +3141,7 @@ pub const fn wrapping_mul(_a: T, _b: T) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `saturating_add` method. For example, /// [`u32::saturating_add`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_saturating", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3216,8 +3158,7 @@ pub const fn saturating_add(_a: T, _b: T) -> T { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `saturating_sub` method. For example, /// [`u32::saturating_sub`] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_saturating", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3231,8 +3172,7 @@ pub const fn saturating_sub(_a: T, _b: T) -> T { /// This intrinsic can *only* be called where the pointer is a local without /// projections (`read_via_copy(ptr)`, not `read_via_copy(*ptr)`) so that it /// trivially obeys runtime-MIR rules about derefs in operands. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_read", since = "1.71.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3246,8 +3186,7 @@ pub const unsafe fn read_via_copy(_ptr: *const T) -> T { /// This intrinsic can *only* be called where the pointer is a local without /// projections (`write_via_move(ptr, x)`, not `write_via_move(*ptr, x)`) so /// that it trivially obeys runtime-MIR rules about derefs in operands. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_write", since = "1.83.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3264,8 +3203,7 @@ pub const unsafe fn write_via_move(_ptr: *mut T, _value: T) { /// any safety invariants. /// /// The stabilized version of this intrinsic is [`core::mem::discriminant`]. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_discriminant", since = "1.75.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3304,8 +3242,7 @@ extern "rust-intrinsic" { } /// See documentation of `<*const T>::offset_from` for details. -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset_from", since = "1.65.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3314,7 +3251,6 @@ pub const unsafe fn ptr_offset_from(_ptr: *const T, _base: *const T) -> isize } /// See documentation of `<*const T>::sub_ptr` for details. -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892"))] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3326,7 +3262,6 @@ pub const unsafe fn ptr_offset_from_unsigned(_ptr: *const T, _base: *const T) /// Returns `2` if the result is unknown. /// Returns `1` if the pointers are guaranteed equal. /// Returns `0` if the pointers are guaranteed inequal. -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020"))] #[rustc_intrinsic] #[rustc_nounwind] #[rustc_do_not_const_check] @@ -3359,7 +3294,6 @@ pub const fn ptr_guaranteed_cmp(ptr: *const T, other: *const T) -> u8 { /// /// (The implementation is allowed to branch on the results of comparisons, /// which is UB if any of their inputs are `undef`.) -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_intrinsic_raw_eq", issue = "none"))] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3381,10 +3315,6 @@ pub const unsafe fn raw_eq(_a: &T, _b: &T) -> bool { /// that differs. That allows optimizations that can read in large chunks. /// /// [valid]: crate::ptr#safety -#[cfg_attr( - bootstrap, - rustc_const_unstable(feature = "const_intrinsic_compare_bytes", issue = "none") -)] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3395,7 +3325,6 @@ pub const unsafe fn compare_bytes(_left: *const u8, _right: *const u8, _bytes: u /// See documentation of [`std::hint::black_box`] for details. /// /// [`std::hint::black_box`]: crate::hint::black_box -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_black_box", issue = "none"))] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -3627,11 +3556,7 @@ pub(crate) macro const_eval_select { /// # _ = foo(&5_i32); /// # _ = bar(&5_i32); /// ``` -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_is_val_statically_known", since = "1.84.0") -)] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] +#[rustc_const_stable_indirect] #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] @@ -3673,8 +3598,7 @@ pub const unsafe fn typed_swap(x: *mut T, y: *mut T) { /// assertions are enabled whenever the *user crate* has UB checks enabled. However, if the /// user has UB checks disabled, the checks will still get optimized out. This intrinsic is /// primarily used by [`ub_checks::assert_unsafe_precondition`]. -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ub_checks", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] // just for UB checks +#[rustc_intrinsic_const_stable_indirect] // just for UB checks #[inline(always)] #[rustc_intrinsic] pub const fn ub_checks() -> bool { @@ -3757,8 +3681,7 @@ pub unsafe fn vtable_align(_ptr: *const ()) -> usize { /// The stabilized version of this intrinsic is [`core::mem::size_of`]. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_size_of", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn size_of() -> usize { @@ -3775,8 +3698,7 @@ pub const fn size_of() -> usize { /// The stabilized version of this intrinsic is [`core::mem::align_of`]. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_min_align_of", since = "1.40.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn min_align_of() -> usize { @@ -3789,7 +3711,6 @@ pub const fn min_align_of() -> usize { /// It's "tracking issue" is [#91971](https://github.com/rust-lang/rust/issues/91971). #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_pref_align_of", issue = "91971"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn pref_align_of() -> usize { @@ -3807,7 +3728,6 @@ pub const unsafe fn pref_align_of() -> usize { /// The to-be-stabilized version of this intrinsic is [`crate::mem::variant_count`]. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "variant_count", issue = "73662"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn variant_count() -> usize { @@ -3823,7 +3743,6 @@ pub const fn variant_count() -> usize { /// See [`crate::mem::size_of_val_raw`] for safety conditions. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_size_of_val", issue = "46571"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn size_of_val(_ptr: *const T) -> usize { @@ -3839,7 +3758,6 @@ pub const unsafe fn size_of_val(_ptr: *const T) -> usize { /// See [`crate::mem::align_of_val_raw`] for safety conditions. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_align_of_val", issue = "46571"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn min_align_of_val(_ptr: *const T) -> usize { @@ -3856,7 +3774,6 @@ pub const unsafe fn min_align_of_val(_ptr: *const T) -> usize { /// The stabilized version of this intrinsic is [`core::any::type_name`]. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_type_name", issue = "63084"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn type_name() -> &'static str { @@ -3875,7 +3792,6 @@ pub const fn type_name() -> &'static str { /// The stabilized version of this intrinsic is [`core::any::TypeId::of`]. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_type_id", issue = "77125"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn type_id() -> u128 { @@ -3889,8 +3805,7 @@ pub const fn type_id() -> u128 { /// change the possible layouts of pointers. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn aggregate_raw_ptr, D, M>(_data: D, _meta: M) -> P { @@ -3915,11 +3830,7 @@ impl AggregateRawPtr<*mut T> for *mut P { /// This is used to implement functions like `ptr::metadata`. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[cfg_attr( - bootstrap, - cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")) -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn ptr_metadata + ?Sized, M>(_ptr: *const P) -> M { @@ -4025,8 +3936,7 @@ pub const fn ptr_metadata + ?Sized, M>(_ptr: *cons #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_copy_nonoverlapping"] pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0"))] - #[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] + #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -4132,8 +4042,7 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_copy"] pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0"))] - #[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] + #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -4216,8 +4125,7 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_write_bytes"] pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_write", since = "1.83.0"))] - #[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] + #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] @@ -4250,7 +4158,6 @@ pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { /// The stabilized version of this intrinsic is /// [`f16::min`] #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f16", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn minnumf16(_x: f16, _y: f16) -> f16 { @@ -4267,11 +4174,7 @@ pub const fn minnumf16(_x: f16, _y: f16) -> f16 { /// The stabilized version of this intrinsic is /// [`f32::min`] #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn minnumf32(_x: f32, _y: f32) -> f32 { @@ -4288,11 +4191,7 @@ pub const fn minnumf32(_x: f32, _y: f32) -> f32 { /// The stabilized version of this intrinsic is /// [`f64::min`] #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn minnumf64(_x: f64, _y: f64) -> f64 { @@ -4309,7 +4208,6 @@ pub const fn minnumf64(_x: f64, _y: f64) -> f64 { /// The stabilized version of this intrinsic is /// [`f128::min`] #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f128", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn minnumf128(_x: f128, _y: f128) -> f128 { @@ -4326,7 +4224,6 @@ pub const fn minnumf128(_x: f128, _y: f128) -> f128 { /// The stabilized version of this intrinsic is /// [`f16::max`] #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f16", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn maxnumf16(_x: f16, _y: f16) -> f16 { @@ -4343,11 +4240,7 @@ pub const fn maxnumf16(_x: f16, _y: f16) -> f16 { /// The stabilized version of this intrinsic is /// [`f32::max`] #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn maxnumf32(_x: f32, _y: f32) -> f32 { @@ -4364,11 +4257,7 @@ pub const fn maxnumf32(_x: f32, _y: f32) -> f32 { /// The stabilized version of this intrinsic is /// [`f64::max`] #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn maxnumf64(_x: f64, _y: f64) -> f64 { @@ -4385,7 +4274,6 @@ pub const fn maxnumf64(_x: f64, _y: f64) -> f64 { /// The stabilized version of this intrinsic is /// [`f128::max`] #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f128", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn maxnumf128(_x: f128, _y: f128) -> f128 { @@ -4397,7 +4285,6 @@ pub const fn maxnumf128(_x: f128, _y: f128) -> f128 { /// The stabilized version of this intrinsic is /// [`f16::abs`](../../std/primitive.f16.html#method.abs) #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f16", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn fabsf16(_x: f16) -> f16 { @@ -4409,11 +4296,7 @@ pub const unsafe fn fabsf16(_x: f16) -> f16 { /// The stabilized version of this intrinsic is /// [`f32::abs`](../../std/primitive.f32.html#method.abs) #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn fabsf32(_x: f32) -> f32 { @@ -4425,11 +4308,7 @@ pub const unsafe fn fabsf32(_x: f32) -> f32 { /// The stabilized version of this intrinsic is /// [`f64::abs`](../../std/primitive.f64.html#method.abs) #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn fabsf64(_x: f64) -> f64 { @@ -4441,7 +4320,6 @@ pub const unsafe fn fabsf64(_x: f64) -> f64 { /// The stabilized version of this intrinsic is /// [`f128::abs`](../../std/primitive.f128.html#method.abs) #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f128", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn fabsf128(_x: f128) -> f128 { @@ -4453,7 +4331,6 @@ pub const unsafe fn fabsf128(_x: f128) -> f128 { /// The stabilized version of this intrinsic is /// [`f16::copysign`](../../std/primitive.f16.html#method.copysign) #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f16", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn copysignf16(_x: f16, _y: f16) -> f16 { @@ -4465,11 +4342,7 @@ pub const unsafe fn copysignf16(_x: f16, _y: f16) -> f16 { /// The stabilized version of this intrinsic is /// [`f32::copysign`](../../std/primitive.f32.html#method.copysign) #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn copysignf32(_x: f32, _y: f32) -> f32 { @@ -4480,11 +4353,7 @@ pub const unsafe fn copysignf32(_x: f32, _y: f32) -> f32 { /// The stabilized version of this intrinsic is /// [`f64::copysign`](../../std/primitive.f64.html#method.copysign) #[rustc_nounwind] -#[cfg_attr( - bootstrap, - rustc_const_stable(feature = "const_float_methods", since = "CURRENT_RUSTC_VERSION") -)] -#[cfg_attr(not(bootstrap), rustc_intrinsic_const_stable_indirect)] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn copysignf64(_x: f64, _y: f64) -> f64 { @@ -4496,7 +4365,6 @@ pub const unsafe fn copysignf64(_x: f64, _y: f64) -> f64 { /// The stabilized version of this intrinsic is /// [`f128::copysign`](../../std/primitive.f128.html#method.copysign) #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f128", issue = "116909"))] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const unsafe fn copysignf128(_x: f128, _y: f128) -> f128 { diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index a178d101254..9c6781f8f41 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -107,9 +107,6 @@ // // Library features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(const_exact_div))] -#![cfg_attr(bootstrap, feature(const_fmt_arguments_new))] -#![cfg_attr(bootstrap, feature(const_ub_checks))] #![feature(array_ptr_get)] #![feature(asm_experimental_arch)] #![feature(const_align_of_val)] @@ -158,8 +155,6 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(strict_provenance))] -#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] @@ -209,6 +204,7 @@ #![feature(simd_ffi)] #![feature(staged_api)] #![feature(stmt_expr_attributes)] +#![feature(strict_provenance_lints)] #![feature(target_feature_11)] #![feature(trait_alias)] #![feature(transparent_unions)] @@ -258,7 +254,6 @@ pub mod assert_matches { } // We don't export this through #[macro_export] for now, to avoid breakage. -#[cfg(not(bootstrap))] #[unstable(feature = "autodiff", issue = "124509")] /// Unstable module containing the unstable `autodiff` macro. pub mod autodiff { diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 771c2d31b60..ab674b58902 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1554,7 +1554,6 @@ pub(crate) mod builtin { #[unstable(feature = "autodiff", issue = "124509")] #[allow_internal_unstable(rustc_attrs)] #[rustc_builtin_macro] - #[cfg(not(bootstrap))] pub macro autodiff($item:item) { /* compiler built-in */ } diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 476a8f823cb..3c1a098374e 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -529,7 +529,7 @@ impl MaybeUninit { /// until they are, it is advisable to avoid them.) #[stable(feature = "maybe_uninit", since = "1.36.0")] #[rustc_const_stable(feature = "const_maybe_uninit_as_ptr", since = "1.59.0")] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline(always)] pub const fn as_ptr(&self) -> *const T { // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer. @@ -571,7 +571,7 @@ impl MaybeUninit { /// until they are, it is advisable to avoid them.) #[stable(feature = "maybe_uninit", since = "1.36.0")] #[rustc_const_stable(feature = "const_maybe_uninit_as_mut_ptr", since = "1.83.0")] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline(always)] pub const fn as_mut_ptr(&mut self) -> *mut T { // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer. @@ -911,10 +911,7 @@ impl MaybeUninit { /// }; /// ``` #[stable(feature = "maybe_uninit_ref", since = "1.55.0")] - #[rustc_const_stable( - feature = "const_maybe_uninit_assume_init", - since = "1.84.0" - )] + #[rustc_const_stable(feature = "const_maybe_uninit_assume_init", since = "1.84.0")] #[inline(always)] pub const unsafe fn assume_init_mut(&mut self) -> &mut T { // SAFETY: the caller must guarantee that `self` is initialized. diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 9e1474ecd1b..aabe8969a91 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1152,7 +1152,6 @@ macro_rules! int_impl { )] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "unchecked_neg", issue = "85122"))] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_neg(self) -> Self { @@ -1217,7 +1216,6 @@ macro_rules! int_impl { /// ``` #[stable(feature = "wrapping", since = "1.7.0")] #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1282,7 +1280,6 @@ macro_rules! int_impl { )] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "unchecked_shifts", issue = "85122"))] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self { @@ -1340,7 +1337,6 @@ macro_rules! int_impl { /// ``` #[stable(feature = "wrapping", since = "1.7.0")] #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1405,7 +1401,6 @@ macro_rules! int_impl { )] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "unchecked_shifts", issue = "85122"))] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self { @@ -2134,7 +2129,6 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] pub const fn wrapping_shl(self, rhs: u32) -> Self { // SAFETY: the masking by the bitsize of the type ensures that we do not shift // out of bounds @@ -2164,7 +2158,6 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] pub const fn wrapping_shr(self, rhs: u32) -> Self { // SAFETY: the masking by the bitsize of the type ensures that we do not shift // out of bounds diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 4278fec9f58..995ed6eac30 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -1449,7 +1449,6 @@ from_str_radix_int_impl! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 } #[doc(hidden)] #[inline(always)] #[unstable(issue = "none", feature = "std_internals")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_from_str", since = "1.82.0"))] pub const fn can_not_overflow(radix: u32, is_signed_ty: bool, digits: &[u8]) -> bool { radix <= 16 && digits.len() <= mem::size_of::() * 2 - is_signed_ty as usize } diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index d398119624a..dfcb13cc1e5 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1434,7 +1434,6 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "wrapping", since = "1.7.0")] #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1499,7 +1498,6 @@ macro_rules! uint_impl { )] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "unchecked_shifts", issue = "85122"))] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self { @@ -1557,7 +1555,6 @@ macro_rules! uint_impl { /// ``` #[stable(feature = "wrapping", since = "1.7.0")] #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.47.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1622,7 +1619,6 @@ macro_rules! uint_impl { )] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "unchecked_shifts", issue = "85122"))] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self { @@ -2193,7 +2189,6 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] pub const fn wrapping_shl(self, rhs: u32) -> Self { // SAFETY: the masking by the bitsize of the type ensures that we do not shift // out of bounds @@ -2226,7 +2221,6 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_shifts))] pub const fn wrapping_shr(self, rhs: u32) -> Self { // SAFETY: the masking by the bitsize of the type ensures that we do not shift // out of bounds @@ -3091,7 +3085,6 @@ macro_rules! uint_impl { // overflow cases it instead ends up returning the maximum value // of the type, and can return 0 for 0. #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_pow", since = "1.50.0"))] const fn one_less_than_next_power_of_two(self) -> Self { if self <= 1 { return 0; } diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index e9bb40d0fdd..c36d55fe2a8 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -405,18 +405,15 @@ unsafe impl DerefPure for &mut T {} /// } /// ``` #[lang = "receiver"] -#[cfg(not(bootstrap))] #[unstable(feature = "arbitrary_self_types", issue = "44874")] pub trait Receiver { /// The target type on which the method may be called. - #[cfg(not(bootstrap))] #[rustc_diagnostic_item = "receiver_target"] #[lang = "receiver_target"] #[unstable(feature = "arbitrary_self_types", issue = "44874")] type Target: ?Sized; } -#[cfg(not(bootstrap))] #[unstable(feature = "arbitrary_self_types", issue = "44874")] impl Receiver for P where @@ -433,8 +430,7 @@ where /// facility based around the current "arbitrary self types" unstable feature. /// That new facility will use the replacement trait above called `Receiver` /// which is why this is now named `LegacyReceiver`. -#[cfg_attr(bootstrap, lang = "receiver")] -#[cfg_attr(not(bootstrap), lang = "legacy_receiver")] +#[lang = "legacy_receiver"] #[unstable(feature = "legacy_receiver_trait", issue = "none")] #[doc(hidden)] pub trait LegacyReceiver { diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index cea1f84f3fd..40526f9583e 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -171,7 +171,6 @@ pub use self::deref::DerefPure; #[unstable(feature = "legacy_receiver_trait", issue = "none")] pub use self::deref::LegacyReceiver; #[unstable(feature = "arbitrary_self_types", issue = "44874")] -#[cfg(not(bootstrap))] pub use self::deref::Receiver; #[stable(feature = "rust1", since = "1.0.0")] pub use self::deref::{Deref, DerefMut}; diff --git a/library/core/src/option.rs b/library/core/src/option.rs index a12fb6a827e..f4ac7af6396 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -563,7 +563,7 @@ use crate::pin::Pin; use crate::{cmp, convert, hint, mem, slice}; /// The `Option` type. See [the module level documentation](self) for more. -#[cfg_attr(not(bootstrap), doc(search_unbox))] +#[doc(search_unbox)] #[derive(Copy, Eq, Debug, Hash)] #[rustc_diagnostic_item = "Option"] #[lang = "Option"] diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs index 1e61cfd804c..5fa340a6147 100644 --- a/library/core/src/panic.rs +++ b/library/core/src/panic.rs @@ -208,14 +208,13 @@ pub macro const_panic { #[rustc_allow_const_fn_unstable(const_eval_select)] #[inline(always)] // inline the wrapper #[track_caller] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_panic", since = "1.84.0"))] const fn do_panic($($arg: $ty),*) -> ! { $crate::intrinsics::const_eval_select!( @capture { $($arg: $ty = $arg),* } -> !: #[noinline] if const #[track_caller] #[inline] { // Inline this, to prevent codegen $crate::panic!($const_msg) - } else #[track_caller] #[cfg_attr(bootstrap, inline)] { // Do not inline this, it makes perf worse + } else #[track_caller] { // Do not inline this, it makes perf worse $crate::panic!($runtime_msg) } ) diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index f603eb2971f..53e2b238bae 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -51,8 +51,7 @@ const _: () = assert!(cfg!(panic = "abort"), "panic_immediate_abort requires -C #[track_caller] #[lang = "panic_fmt"] // needed for const-evaluated panics #[rustc_do_not_const_check] // hooked by const-eval -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { if cfg!(feature = "panic_immediate_abort") { super::intrinsics::abort() @@ -86,8 +85,7 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { // and unwinds anyway, we will hit the "unwinding out of nounwind function" guard, // which causes a "panic in a function that cannot unwind". #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable #[rustc_allow_const_fn_unstable(const_eval_select)] pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: bool) -> ! { const_eval_select!( @@ -130,8 +128,7 @@ pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: boo #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable #[lang = "panic"] // used by lints and miri for panics pub const fn panic(expr: &'static str) -> ! { // Use Arguments::new_const instead of format_args!("{expr}") to potentially @@ -169,8 +166,7 @@ macro_rules! panic_const { #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] - #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable + #[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable #[lang = stringify!($lang)] pub const fn $lang() -> ! { // Use Arguments::new_const instead of format_args!("{expr}") to potentially @@ -217,8 +213,7 @@ panic_const! { #[cfg_attr(feature = "panic_immediate_abort", inline)] #[lang = "panic_nounwind"] // needed by codegen for non-unwinding panics #[rustc_nounwind] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable pub const fn panic_nounwind(expr: &'static str) -> ! { panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]), /* force_no_backtrace */ false); } @@ -234,8 +229,7 @@ pub fn panic_nounwind_nobacktrace(expr: &'static str) -> ! { #[track_caller] #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable pub const fn panic_explicit() -> ! { panic_display(&"explicit panic"); } @@ -252,8 +246,7 @@ pub fn unreachable_display(x: &T) -> ! { #[inline] #[track_caller] #[rustc_diagnostic_item = "panic_str_2015"] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable pub const fn panic_str_2015(expr: &str) -> ! { panic_display(&expr); } @@ -263,8 +256,7 @@ pub const fn panic_str_2015(expr: &str) -> ! { #[rustc_do_not_const_check] // hooked by const-eval // enforce a &&str argument in const-check and hook this by const-eval #[rustc_const_panic_str] -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable pub const fn panic_display(x: &T) -> ! { panic_fmt(format_args!("{}", *x)); } @@ -333,8 +325,7 @@ fn panic_in_cleanup() -> ! { /// This function is used instead of panic_fmt in const eval. #[lang = "const_panic_fmt"] // needed by const-eval machine to replace calls to `panic_fmt` lang item -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))] -#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable +#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable pub const fn const_panic_fmt(fmt: fmt::Arguments<'_>) -> ! { if let Some(msg) = fmt.as_str() { // The panic_display function is hooked by const eval. diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index 2538d60a8ee..74a1d40f4e7 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -41,7 +41,6 @@ impl Alignment { /// This provides the same numerical value as [`mem::align_of`], /// but in an `Alignment` instead of a `usize`. #[unstable(feature = "ptr_alignment_type", issue = "102070")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))] #[inline] pub const fn of() -> Self { // SAFETY: rustc ensures that type alignment is always a power of two. @@ -53,7 +52,6 @@ impl Alignment { /// /// Note that `0` is not a power of two, nor a valid alignment. #[unstable(feature = "ptr_alignment_type", issue = "102070")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))] #[inline] pub const fn new(align: usize) -> Option { if align.is_power_of_two() { @@ -73,7 +71,6 @@ impl Alignment { /// Equivalently, it must be `1 << exp` for some `exp` in `0..usize::BITS`. /// It must *not* be zero. #[unstable(feature = "ptr_alignment_type", issue = "102070")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))] #[inline] pub const unsafe fn new_unchecked(align: usize) -> Self { assert_unsafe_precondition!( @@ -89,7 +86,6 @@ impl Alignment { /// Returns the alignment as a [`usize`]. #[unstable(feature = "ptr_alignment_type", issue = "102070")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))] #[inline] pub const fn as_usize(self) -> usize { self.0 as usize @@ -97,7 +93,6 @@ impl Alignment { /// Returns the alignment as a [NonZero]<[usize]>. #[unstable(feature = "ptr_alignment_type", issue = "102070")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))] #[inline] pub const fn as_nonzero(self) -> NonZero { // SAFETY: All the discriminants are non-zero. @@ -118,7 +113,6 @@ impl Alignment { /// assert_eq!(Alignment::new(1024).unwrap().log2(), 10); /// ``` #[unstable(feature = "ptr_alignment_type", issue = "102070")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))] #[inline] pub const fn log2(self) -> u32 { self.as_nonzero().trailing_zeros() @@ -148,7 +142,6 @@ impl Alignment { /// assert_ne!(one.mask(Alignment::of::().mask()), one); /// ``` #[unstable(feature = "ptr_alignment_type", issue = "102070")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))] #[inline] pub const fn mask(self) -> usize { // SAFETY: The alignment is always nonzero, and therefore decrementing won't overflow. diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index dfe905544af..78d9a1b04c8 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -113,7 +113,6 @@ impl *const T { /// println!("{:?}", unsafe { &*bad }); /// ``` #[unstable(feature = "set_ptr_value", issue = "75091")] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))] #[must_use = "returns a new pointer rather than modifying its argument"] #[inline] pub const fn with_metadata_of(self, meta: *const U) -> *const U @@ -1018,7 +1017,6 @@ impl *const T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[must_use = "returns a new pointer rather than modifying its argument"] #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_neg))] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn sub(self, count: usize) -> Self diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index 5f20cb2ee72..ae9810e558a 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -92,7 +92,6 @@ pub trait Thin = Pointee; /// /// assert_eq!(std::ptr::metadata("foo"), 3_usize); /// ``` -#[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))] #[inline] pub const fn metadata(ptr: *const T) -> ::Metadata { ptr_metadata(ptr) @@ -106,7 +105,6 @@ pub const fn metadata(ptr: *const T) -> ::Metadata { /// /// [`slice::from_raw_parts`]: crate::slice::from_raw_parts #[unstable(feature = "ptr_metadata", issue = "81513")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))] #[inline] pub const fn from_raw_parts( data_pointer: *const impl Thin, @@ -120,7 +118,6 @@ pub const fn from_raw_parts( /// /// See the documentation of [`from_raw_parts`] for more details. #[unstable(feature = "ptr_metadata", issue = "81513")] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))] #[inline] pub const fn from_raw_parts_mut( data_pointer: *mut impl Thin, diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 5ed0b39f33b..0a827914245 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -94,7 +94,6 @@ impl *mut T { /// // This dereference is UB. The pointer only has provenance for `x` but points to `y`. /// println!("{:?}", unsafe { &*bad }); #[unstable(feature = "set_ptr_value", issue = "75091")] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))] #[must_use = "returns a new pointer rather than modifying its argument"] #[inline] pub const fn with_metadata_of(self, meta: *const U) -> *mut U @@ -1097,7 +1096,6 @@ impl *mut T { #[stable(feature = "pointer_methods", since = "1.26.0")] #[must_use = "returns a new pointer rather than modifying its argument"] #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_neg))] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn sub(self, count: usize) -> Self diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 0fb5880fd1a..d37b7eedfcb 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -629,7 +629,6 @@ impl NonNull { #[must_use = "returns a new pointer rather than modifying its argument"] #[stable(feature = "non_null_convenience", since = "1.80.0")] #[rustc_const_stable(feature = "non_null_convenience", since = "1.80.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(unchecked_neg))] pub const unsafe fn sub(self, count: usize) -> Self where T: Sized, diff --git a/library/core/src/result.rs b/library/core/src/result.rs index b450123c5aa..9c7be618bc7 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -520,7 +520,7 @@ use crate::{convert, fmt, hint}; /// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]). /// /// See the [module documentation](self) for details. -#[cfg_attr(not(bootstrap), doc(search_unbox))] +#[doc(search_unbox)] #[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] #[must_use = "this `Result` may be an `Err` variant, which should be handled"] #[rustc_diagnostic_item = "Result"] diff --git a/library/core/src/slice/memchr.rs b/library/core/src/slice/memchr.rs index 339adad1b17..98db7aaf533 100644 --- a/library/core/src/slice/memchr.rs +++ b/library/core/src/slice/memchr.rs @@ -16,7 +16,6 @@ const USIZE_BYTES: usize = mem::size_of::(); /// bytes where the borrow propagated all the way to the most significant /// bit." #[inline] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_memchr", since = "1.65.0"))] const fn contains_zero_byte(x: usize) -> bool { x.wrapping_sub(LO_USIZE) & !x & HI_USIZE != 0 } @@ -24,7 +23,6 @@ const fn contains_zero_byte(x: usize) -> bool { /// Returns the first index matching the byte `x` in `text`. #[inline] #[must_use] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_memchr", since = "1.65.0"))] pub const fn memchr(x: u8, text: &[u8]) -> Option { // Fast path for small slices. if text.len() < 2 * USIZE_BYTES { @@ -35,7 +33,6 @@ pub const fn memchr(x: u8, text: &[u8]) -> Option { } #[inline] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_memchr", since = "1.65.0"))] const fn memchr_naive(x: u8, text: &[u8]) -> Option { let mut i = 0; @@ -52,7 +49,6 @@ const fn memchr_naive(x: u8, text: &[u8]) -> Option { } #[rustc_allow_const_fn_unstable(const_eval_select)] // fallback impl has same behavior -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_memchr", since = "1.65.0"))] const fn memchr_aligned(x: u8, text: &[u8]) -> Option { // The runtime version behaves the same as the compiletime version, it's // just more optimized. diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index b3defba5a98..498e4ea286c 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -735,7 +735,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_slice_as_ptr", since = "1.32.0")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline(always)] #[must_use] pub const fn as_ptr(&self) -> *const T { @@ -766,7 +766,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[inline(always)] #[must_use] pub const fn as_mut_ptr(&mut self) -> *mut T { diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 189ab39e976..8a473b398bb 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -373,7 +373,7 @@ impl str { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "rustc_str_as_ptr", since = "1.32.0")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[must_use] #[inline(always)] pub const fn as_ptr(&self) -> *const u8 { @@ -391,7 +391,7 @@ impl str { #[stable(feature = "str_as_mut_ptr", since = "1.36.0")] #[rustc_const_stable(feature = "const_str_as_mut", since = "1.83.0")] #[rustc_never_returns_null_ptr] - #[cfg_attr(not(bootstrap), rustc_as_ptr)] + #[rustc_as_ptr] #[must_use] #[inline(always)] pub const fn as_mut_ptr(&mut self) -> *mut u8 { diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 34673707f01..41e9c593ebd 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -319,7 +319,6 @@ impl<'a> ContextBuilder<'a> { /// Creates a ContextBuilder from a Waker. #[inline] #[unstable(feature = "local_waker", issue = "118959")] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_waker", since = "1.82.0"))] pub const fn from_waker(waker: &'a Waker) -> Self { // SAFETY: LocalWaker is just Waker without thread safety let local_waker = unsafe { transmute(waker) }; @@ -373,7 +372,6 @@ impl<'a> ContextBuilder<'a> { /// Builds the `Context`. #[inline] #[unstable(feature = "local_waker", issue = "118959")] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_waker", since = "1.82.0"))] pub const fn build(self) -> Context<'a> { let ContextBuilder { waker, local_waker, ext, _marker, _marker2 } = self; Context { waker, local_waker, ext: AssertUnwindSafe(ext), _marker, _marker2 } diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs index 3e6110c9c88..b289f6026ff 100644 --- a/library/core/src/ub_checks.rs +++ b/library/core/src/ub_checks.rs @@ -47,7 +47,6 @@ use crate::intrinsics::{self, const_eval_select}; /// order to call it. Since the precompiled standard library is built with full debuginfo and these /// variables cannot be optimized out in MIR, an innocent-looking `let` can produce enough /// debuginfo to have a measurable compile-time impact on debug builds. -#[cfg_attr(bootstrap, allow_internal_unstable(const_ub_checks))] // permit this to be called in stably-const fn #[macro_export] #[unstable(feature = "ub_checks", issue = "none")] macro_rules! assert_unsafe_precondition { @@ -89,7 +88,6 @@ pub use intrinsics::ub_checks as check_library_ub; /// /// The intention is to not do that when running in the interpreter, as that one has its own /// language UB checks which generally produce better errors. -#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ub_checks", issue = "none"))] #[inline] #[rustc_allow_const_fn_unstable(const_eval_select)] pub(crate) const fn check_language_ub() -> bool { diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index 7f4826402eb..4655d35e9c4 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -1,7 +1,6 @@ ///! This file is generated by `./x run src/tools/unicode-table-generator`; do not edit manually! #[inline(always)] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0"))] const fn bitset_search< const N: usize, const CHUNK_SIZE: usize, @@ -424,7 +423,6 @@ pub mod lowercase { (5, 187), (6, 78), (7, 132), ]; - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0"))] pub const fn lookup(c: char) -> bool { super::bitset_search( c as u32, @@ -549,7 +547,6 @@ pub mod uppercase { (2, 146), (2, 20), (3, 146), (3, 140), (3, 134), (4, 178), (4, 171), ]; - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0"))] pub const fn lookup(c: char) -> bool { super::bitset_search( c as u32, diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index f7825571cd7..40129619ce5 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -1,7 +1,4 @@ // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(const_three_way_compare))] -#![cfg_attr(bootstrap, feature(strict_provenance))] -#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] #![cfg_attr(test, feature(cfg_match))] #![feature(alloc_layout_extra)] @@ -83,6 +80,7 @@ #![feature(step_trait)] #![feature(str_internals)] #![feature(strict_provenance_atomic_ptr)] +#![feature(strict_provenance_lints)] #![feature(test)] #![feature(trait_upcasting)] #![feature(trusted_len)] diff --git a/library/panic_unwind/Cargo.toml b/library/panic_unwind/Cargo.toml index 6d1f9764efb..252f118fecf 100644 --- a/library/panic_unwind/Cargo.toml +++ b/library/panic_unwind/Cargo.toml @@ -23,7 +23,4 @@ libc = { version = "0.2", default-features = false } [lints.rust.unexpected_cfgs] level = "warn" -check-cfg = [ - # #[cfg(bootstrap)] rtems - 'cfg(target_os, values("rtems"))', -] +check-cfg = [] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index c1ab70b714a..260732dee18 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -144,6 +144,4 @@ check-cfg = [ # and to the `backtrace` crate which messes-up with Cargo list # of declared features, we therefor expect any feature cfg 'cfg(feature, values(any()))', - # #[cfg(bootstrap)] rtems - 'cfg(target_os, values("rtems"))', ] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index cf99a618e55..70a2e7fdb78 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -262,7 +262,6 @@ #![allow(unused_features)] // // Features: -#![cfg_attr(not(bootstrap), feature(autodiff))] #![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count, rt))] #![cfg_attr( all(target_vendor = "fortanix", target_env = "sgx"), @@ -274,13 +273,12 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(strict_provenance))] -#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] #![feature(alloc_error_handler)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] #![feature(allow_internal_unstable)] #![feature(asm_experimental_arch)] +#![feature(autodiff)] #![feature(cfg_sanitizer_cfi)] #![feature(cfg_target_thread_local)] #![feature(cfi_encoding)] @@ -314,6 +312,7 @@ #![feature(rustdoc_internals)] #![feature(staged_api)] #![feature(stmt_expr_attributes)] +#![feature(strict_provenance_lints)] #![feature(thread_local)] #![feature(try_blocks)] #![feature(type_alias_impl_trait)] @@ -622,7 +621,6 @@ pub mod simd { #[doc(inline)] pub use crate::std_float::StdFloat; } -#[cfg(not(bootstrap))] #[unstable(feature = "autodiff", issue = "124509")] /// This module provides support for automatic differentiation. pub mod autodiff { diff --git a/library/std/src/sys/sync/condvar/no_threads.rs b/library/std/src/sys/sync/condvar/no_threads.rs index 2a67ed766aa..88ce39305e1 100644 --- a/library/std/src/sys/sync/condvar/no_threads.rs +++ b/library/std/src/sys/sync/condvar/no_threads.rs @@ -5,7 +5,6 @@ pub struct Condvar {} impl Condvar { #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_locks", since = "1.63.0"))] pub const fn new() -> Condvar { Condvar {} } diff --git a/library/std/src/sys/sync/mutex/no_threads.rs b/library/std/src/sys/sync/mutex/no_threads.rs index 7b243575e01..57c78f454c5 100644 --- a/library/std/src/sys/sync/mutex/no_threads.rs +++ b/library/std/src/sys/sync/mutex/no_threads.rs @@ -10,7 +10,6 @@ unsafe impl Sync for Mutex {} // no threads on this platform impl Mutex { #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_locks", since = "1.63.0"))] pub const fn new() -> Mutex { Mutex { locked: Cell::new(false) } } diff --git a/library/std/src/sys/sync/once/no_threads.rs b/library/std/src/sys/sync/once/no_threads.rs index fb1b496510a..88a1d50361e 100644 --- a/library/std/src/sys/sync/once/no_threads.rs +++ b/library/std/src/sys/sync/once/no_threads.rs @@ -35,7 +35,6 @@ unsafe impl Sync for Once {} impl Once { #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_once_new", since = "1.32.0"))] pub const fn new() -> Once { Once { state: Cell::new(State::Incomplete) } } diff --git a/library/std/src/sys/sync/once/queue.rs b/library/std/src/sys/sync/once/queue.rs index 87837915b39..5beff4ce683 100644 --- a/library/std/src/sys/sync/once/queue.rs +++ b/library/std/src/sys/sync/once/queue.rs @@ -116,7 +116,6 @@ fn to_state(current: StateAndQueue) -> usize { impl Once { #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_once_new", since = "1.32.0"))] pub const fn new() -> Once { Once { state_and_queue: AtomicPtr::new(ptr::without_provenance_mut(INCOMPLETE)) } } diff --git a/library/std/src/sys/sync/rwlock/no_threads.rs b/library/std/src/sys/sync/rwlock/no_threads.rs index c11e59f719e..573d0d602db 100644 --- a/library/std/src/sys/sync/rwlock/no_threads.rs +++ b/library/std/src/sys/sync/rwlock/no_threads.rs @@ -10,7 +10,6 @@ unsafe impl Sync for RwLock {} // no threads on this platform impl RwLock { #[inline] - #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_locks", since = "1.63.0"))] pub const fn new() -> RwLock { RwLock { mode: Cell::new(0) } } diff --git a/library/std/src/sys/thread_local/key/racy.rs b/library/std/src/sys/thread_local/key/racy.rs index 97df8997b80..e1bc08eabb3 100644 --- a/library/std/src/sys/thread_local/key/racy.rs +++ b/library/std/src/sys/thread_local/key/racy.rs @@ -30,7 +30,6 @@ const KEY_SENTVAL: usize = 0; const KEY_SENTVAL: usize = libc::PTHREAD_KEYS_MAX + 1; impl LazyKey { - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "thread_local_internals", issue = "none"))] pub const fn new(dtor: Option) -> LazyKey { LazyKey { key: atomic::AtomicUsize::new(KEY_SENTVAL), dtor } } diff --git a/library/std/src/sys/thread_local/os.rs b/library/std/src/sys/thread_local/os.rs index 58f291ffdb9..00d2e30bd60 100644 --- a/library/std/src/sys/thread_local/os.rs +++ b/library/std/src/sys/thread_local/os.rs @@ -60,7 +60,6 @@ struct Value { } impl Storage { - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "thread_local_internals", issue = "none"))] pub const fn new() -> Storage { Storage { key: LazyKey::new(Some(destroy_value::)), marker: PhantomData } } diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 9edb3fa4193..5c5d694f83d 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -237,7 +237,6 @@ impl LocalKey { reason = "recently added to create a key", issue = "none" )] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "thread_local_internals", issue = "none"))] pub const unsafe fn new(inner: fn(Option<&mut Option>) -> *const T) -> LocalKey { LocalKey { inner } } diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml index 569a1b3299e..96ddae16f0a 100644 --- a/library/unwind/Cargo.toml +++ b/library/unwind/Cargo.toml @@ -37,7 +37,4 @@ system-llvm-libunwind = [] [lints.rust.unexpected_cfgs] level = "warn" -check-cfg = [ - # #[cfg(bootstrap)] rtems - 'cfg(target_os, values("rtems"))', -] +check-cfg = [] diff --git a/src/tools/unicode-table-generator/src/range_search.rs b/src/tools/unicode-table-generator/src/range_search.rs index 14da876eda7..9a51979a2f0 100644 --- a/src/tools/unicode-table-generator/src/range_search.rs +++ b/src/tools/unicode-table-generator/src/range_search.rs @@ -1,5 +1,4 @@ #[inline(always)] -#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0"))] const fn bitset_search< const N: usize, const CHUNK_SIZE: usize, diff --git a/src/tools/unicode-table-generator/src/raw_emitter.rs b/src/tools/unicode-table-generator/src/raw_emitter.rs index dd064c59283..46010692fe5 100644 --- a/src/tools/unicode-table-generator/src/raw_emitter.rs +++ b/src/tools/unicode-table-generator/src/raw_emitter.rs @@ -97,10 +97,6 @@ impl RawEmitter { self.blank_line(); - writeln!( - &mut self.file, - r#"#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_unicode_case_lookup", since = "1.84.0"))]"# - ).unwrap(); writeln!(&mut self.file, "pub const fn lookup(c: char) -> bool {{").unwrap(); if first_code_point > 0x7f { writeln!(&mut self.file, " (c as u32) >= {first_code_point:#04x} &&").unwrap(); -- cgit 1.4.1-3-g733a5 From 79b4f25c344bb6083af18d61dcfc0df68aec1ea9 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Thu, 28 Nov 2024 04:57:22 +0000 Subject: Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/tools') diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index e5812ae2603..e193c786eff 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -5d3c6ee9b34989595d2a72b79e61ca37e949d757 +eddb717281a9031f645d88dd3b8323a7e25632cc -- cgit 1.4.1-3-g733a5 From 2039a9fac08ae8dd214826e254c3a7d300cb0360 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Thu, 28 Nov 2024 05:06:38 +0000 Subject: fmt --- src/tools/miri/src/shims/windows/foreign_items.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/tools') diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index a1fad6f9af4..d6a180451d7 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -383,7 +383,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_int(1, dest)?; } "TlsFree" => { - let [key] = this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [key] = + this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; let key = u128::from(this.read_scalar(key)?.to_u32()?); this.machine.tls.delete_tls_key(key)?; -- cgit 1.4.1-3-g733a5 From 8e2d72bac8e29cda5b1457720dcdc66def70d9d4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 28 Nov 2024 08:38:48 +0100 Subject: silence clippy --- src/tools/miri/src/bin/miri.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/tools') diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index c61c62c73da..15f05ba909c 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -3,6 +3,7 @@ clippy::manual_range_contains, clippy::useless_format, clippy::field_reassign_with_default, + clippy::needless_lifetimes, rustc::diagnostic_outside_of_impl, rustc::untranslatable_diagnostic )] -- cgit 1.4.1-3-g733a5 From c2cb99378a3d44ce3a5d8c158647e6da54049a0a Mon Sep 17 00:00:00 2001 From: klensy Date: Thu, 28 Nov 2024 14:02:03 +0300 Subject: remove ctrlc, unused --- src/tools/miri/Cargo.lock | 29 ----------------------------- src/tools/miri/Cargo.toml | 1 - 2 files changed, 30 deletions(-) (limited to 'src/tools') diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index 05d1c2d1eb3..01e32229f25 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -150,12 +150,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - [[package]] name = "chrono" version = "0.4.38" @@ -286,16 +280,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "ctrlc" -version = "3.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345" -dependencies = [ - "nix", - "windows-sys 0.52.0", -] - [[package]] name = "directories" version = "5.0.1" @@ -554,7 +538,6 @@ dependencies = [ "chrono", "chrono-tz", "colored", - "ctrlc", "directories", "getrandom", "jemalloc-sys", @@ -571,18 +554,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "nix" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" -dependencies = [ - "bitflags", - "cfg-if", - "cfg_aliases", - "libc", -] - [[package]] name = "num-traits" version = "0.2.19" diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index cb02914fd93..d1cd3640346 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -23,7 +23,6 @@ rand = "0.8" smallvec = { version = "1.7", features = ["drain_filter"] } aes = { version = "0.8.3", features = ["hazmat"] } measureme = "11" -ctrlc = "3.2.5" chrono = { version = "0.4.38", default-features = false } chrono-tz = "0.10" directories = "5" -- cgit 1.4.1-3-g733a5 From c52d952a6aae3c850dba192a79662b990eb8dc11 Mon Sep 17 00:00:00 2001 From: Maybe Lapkin Date: Thu, 28 Nov 2024 20:31:08 +0100 Subject: add instructions for generating `flake.lock` to `envrc-flake` Previous setup instructions did not work without. (i.e. the envrc would not do anything, `nix flake show..` would provide unhelpful error) --- src/tools/nix-dev-shell/envrc-flake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/tools') diff --git a/src/tools/nix-dev-shell/envrc-flake b/src/tools/nix-dev-shell/envrc-flake index 218d88d8721..9def420f05c 100644 --- a/src/tools/nix-dev-shell/envrc-flake +++ b/src/tools/nix-dev-shell/envrc-flake @@ -1,7 +1,7 @@ # If you want to use this as an .envrc file to create a shell with necessery components # to develop rustc, use the following command in the root of the rusr checkout: # -# ln -s ./src/tools/nix-dev-shell/envrc-flake ./.envrc && echo .envrc >> .git/info/exclude +# ln -s ./src/tools/nix-dev-shell/envrc-flake ./.envrc && nix flake update --flake ./src/tools/nix-dev-shell && echo .envrc >> .git/info/exclude if nix flake show path:./src/tools/nix-dev-shell &> /dev/null; then use flake path:./src/tools/nix-dev-shell -- cgit 1.4.1-3-g733a5 From 688f28d67065be8d67648dc395e288fcaababbb0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 25 Nov 2024 13:08:54 +1100 Subject: Stop using `HybridBitSet` in clippy. The compiler uses `BitSet`, because the number of locals doesn't get that high, so clippy should do likewise. --- src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs | 10 +++++----- src/tools/clippy/clippy_utils/src/mir/possible_origin.rs | 4 ++-- src/tools/clippy/clippy_utils/src/mir/transitive_relation.rs | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/tools') diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs index 6b3078f52af..17e6558a41c 100644 --- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs +++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs @@ -2,7 +2,7 @@ use super::possible_origin::PossibleOriginVisitor; use super::transitive_relation::TransitiveRelation; use crate::ty::is_copy; use rustc_data_structures::fx::FxHashMap; -use rustc_index::bit_set::{BitSet, HybridBitSet}; +use rustc_index::bit_set::BitSet; use rustc_lint::LateContext; use rustc_middle::mir::visit::Visitor as _; use rustc_middle::mir::{self, Mutability}; @@ -21,14 +21,14 @@ struct PossibleBorrowerVisitor<'a, 'b, 'tcx> { possible_borrower: TransitiveRelation, body: &'b mir::Body<'tcx>, cx: &'a LateContext<'tcx>, - possible_origin: FxHashMap>, + possible_origin: FxHashMap>, } impl<'a, 'b, 'tcx> PossibleBorrowerVisitor<'a, 'b, 'tcx> { fn new( cx: &'a LateContext<'tcx>, body: &'b mir::Body<'tcx>, - possible_origin: FxHashMap>, + possible_origin: FxHashMap>, ) -> Self { Self { possible_borrower: TransitiveRelation::default(), @@ -119,7 +119,7 @@ impl<'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'_, '_, 'tcx> { let mut mutable_variables: Vec = mutable_borrowers .iter() .filter_map(|r| self.possible_origin.get(r)) - .flat_map(HybridBitSet::iter) + .flat_map(BitSet::iter) .collect(); if ContainsRegion.visit_ty(self.body.local_decls[*dest].ty).is_break() { @@ -171,7 +171,7 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) { #[allow(clippy::module_name_repetitions)] pub struct PossibleBorrowerMap<'b, 'tcx> { /// Mapping `Local -> its possible borrowers` - pub map: FxHashMap>, + pub map: FxHashMap>, maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive<'tcx>>, // Caches to avoid allocation of `BitSet` on every query pub bitset: (BitSet, BitSet), diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs b/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs index 4157b3f4930..47b93aad20c 100644 --- a/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs +++ b/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs @@ -1,7 +1,7 @@ use super::transitive_relation::TransitiveRelation; use crate::ty::is_copy; use rustc_data_structures::fx::FxHashMap; -use rustc_index::bit_set::HybridBitSet; +use rustc_index::bit_set::BitSet; use rustc_lint::LateContext; use rustc_middle::mir; @@ -22,7 +22,7 @@ impl<'a, 'tcx> PossibleOriginVisitor<'a, 'tcx> { } } - pub fn into_map(self, cx: &LateContext<'tcx>) -> FxHashMap> { + pub fn into_map(self, cx: &LateContext<'tcx>) -> FxHashMap> { let mut map = FxHashMap::default(); for row in (1..self.body.local_decls.len()).map(mir::Local::from_usize) { if is_copy(cx, self.body.local_decls[row].ty) { diff --git a/src/tools/clippy/clippy_utils/src/mir/transitive_relation.rs b/src/tools/clippy/clippy_utils/src/mir/transitive_relation.rs index 7fe2960739f..74d1f60af71 100644 --- a/src/tools/clippy/clippy_utils/src/mir/transitive_relation.rs +++ b/src/tools/clippy/clippy_utils/src/mir/transitive_relation.rs @@ -1,5 +1,5 @@ use rustc_data_structures::fx::FxHashMap; -use rustc_index::bit_set::HybridBitSet; +use rustc_index::bit_set::BitSet; use rustc_middle::mir; #[derive(Default)] @@ -12,8 +12,8 @@ impl TransitiveRelation { self.relations.entry(a).or_default().push(b); } - pub fn reachable_from(&self, a: mir::Local, domain_size: usize) -> HybridBitSet { - let mut seen = HybridBitSet::new_empty(domain_size); + pub fn reachable_from(&self, a: mir::Local, domain_size: usize) -> BitSet { + let mut seen = BitSet::new_empty(domain_size); let mut stack = vec![a]; while let Some(u) = stack.pop() { if let Some(edges) = self.relations.get(&u) { -- cgit 1.4.1-3-g733a5 From 998ff2f0cd2902e86178d35b01ba78fe4633f80b Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Fri, 29 Nov 2024 18:43:48 +0000 Subject: Move the `crate-loading` test to use `diff` output --- .../run-make-support/src/external_deps/rustc.rs | 6 + .../crate-loading/multiple-dep-versions.stderr | 127 +++++++++++++++++++++ tests/run-make/crate-loading/rmake.rs | 95 +++------------ 3 files changed, 152 insertions(+), 76 deletions(-) create mode 100644 tests/run-make/crate-loading/multiple-dep-versions.stderr (limited to 'src/tools') diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs index 494daeca963..ffe10092cc2 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -227,6 +227,12 @@ impl Rustc { self } + /// Normalize the line number in the stderr output + pub fn ui_testing(&mut self) -> &mut Self { + self.cmd.arg(format!("-Zui-testing")); + self + } + /// Specify the target triple, or a path to a custom target json spec file. pub fn target>(&mut self, target: S) -> &mut Self { let target = target.as_ref(); diff --git a/tests/run-make/crate-loading/multiple-dep-versions.stderr b/tests/run-make/crate-loading/multiple-dep-versions.stderr new file mode 100644 index 00000000000..5888aad8f37 --- /dev/null +++ b/tests/run-make/crate-loading/multiple-dep-versions.stderr @@ -0,0 +1,127 @@ +error[E0277]: the trait bound `dep_2_reexport::Type: Trait` is not satisfied + --> replaced + | +LL | do_something(Type); + | ------------ ^^^^ the trait `Trait` is not implemented for `dep_2_reexport::Type` + | | + | required by a bound introduced by this call + | +note: there are multiple different versions of crate `dependency` in the dependency graph + --> replaced + | +LL | pub struct Type(pub i32); + | --------------- this type implements the required trait +LL | pub trait Trait { + | ^^^^^^^^^^^^^^^ this is the required trait + | + ::: replaced + | +LL | extern crate dep_2_reexport; + | ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo` +LL | extern crate dependency; + | ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate + | + ::: replaced + | +LL | pub struct Type; + | --------------- this type doesn't implement the required trait +LL | pub trait Trait { + | --------------- this is the found trait + = note: two types coming from two different versions of the same crate are different types even if they look the same + = help: you can use `cargo tree` to explore your dependency tree +note: required by a bound in `do_something` + --> replaced + | +LL | pub fn do_something(_: X) {} + | ^^^^^ required by this bound in `do_something` + +error[E0599]: no method named `foo` found for struct `dep_2_reexport::Type` in the current scope + --> replaced + | +LL | Type.foo(); + | ^^^ method not found in `Type` + | +note: there are multiple different versions of crate `dependency` in the dependency graph + --> replaced + | +LL | pub trait Trait { + | ^^^^^^^^^^^^^^^ this is the trait that is needed +LL | fn foo(&self); + | -------------- the method is available for `dep_2_reexport::Type` here + | + ::: replaced + | +LL | use dependency::{Trait, do_something}; + | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency` + | + ::: replaced + | +LL | pub trait Trait { + | --------------- this is the trait that was imported + +error[E0599]: no function or associated item named `bar` found for struct `dep_2_reexport::Type` in the current scope + --> replaced + | +LL | Type::bar(); + | ^^^ function or associated item not found in `Type` + | +note: there are multiple different versions of crate `dependency` in the dependency graph + --> replaced + | +LL | pub trait Trait { + | ^^^^^^^^^^^^^^^ this is the trait that is needed +LL | fn foo(&self); +LL | fn bar(); + | --------- the associated function is available for `dep_2_reexport::Type` here + | + ::: replaced + | +LL | use dependency::{Trait, do_something}; + | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency` + | + ::: replaced + | +LL | pub trait Trait { + | --------------- this is the trait that was imported + +error[E0277]: the trait bound `OtherType: Trait` is not satisfied + --> replaced + | +LL | do_something(OtherType); + | ------------ ^^^^^^^^^ the trait `Trait` is not implemented for `OtherType` + | | + | required by a bound introduced by this call + | +note: there are multiple different versions of crate `dependency` in the dependency graph + --> replaced + | +LL | pub trait Trait { + | ^^^^^^^^^^^^^^^ this is the required trait + | + ::: replaced + | +LL | extern crate dep_2_reexport; + | ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo` +LL | extern crate dependency; + | ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate + | + ::: replaced + | +LL | pub struct OtherType; + | -------------------- this type doesn't implement the required trait + | + ::: replaced + | +LL | pub trait Trait { + | --------------- this is the found trait + = help: you can use `cargo tree` to explore your dependency tree +note: required by a bound in `do_something` + --> replaced + | +LL | pub fn do_something(_: X) {} + | ^^^^^ required by this bound in `do_something` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. \ No newline at end of file diff --git a/tests/run-make/crate-loading/rmake.rs b/tests/run-make/crate-loading/rmake.rs index 544bf9ab957..6ad456e3e3e 100644 --- a/tests/run-make/crate-loading/rmake.rs +++ b/tests/run-make/crate-loading/rmake.rs @@ -3,7 +3,7 @@ //@ ignore-wasm64 // ignore-tidy-linelength -use run_make_support::{rust_lib_name, rustc}; +use run_make_support::{diff, rust_lib_name, rustc}; fn main() { rustc().input("multiple-dep-versions-1.rs").run(); @@ -13,83 +13,26 @@ fn main() { .extern_("dependency", rust_lib_name("dependency2")) .run(); - rustc() + let out = rustc() .input("multiple-dep-versions.rs") .extern_("dependency", rust_lib_name("dependency")) .extern_("dep_2_reexport", rust_lib_name("foo")) + .ui_testing() .run_fail() - .assert_stderr_contains(r#"error[E0277]: the trait bound `dep_2_reexport::Type: Trait` is not satisfied - --> multiple-dep-versions.rs:7:18 - | -7 | do_something(Type); - | ------------ ^^^^ the trait `Trait` is not implemented for `dep_2_reexport::Type` - | | - | required by a bound introduced by this call - | -note: there are multiple different versions of crate `dependency` in the dependency graph"#) - .assert_stderr_contains(r#" -3 | pub struct Type(pub i32); - | --------------- this type implements the required trait -4 | pub trait Trait { - | ^^^^^^^^^^^^^^^ this is the required trait -"#) - .assert_stderr_contains(r#" -1 | extern crate dep_2_reexport; - | ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo` -2 | extern crate dependency; - | ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate"#) - .assert_stderr_contains(r#" -3 | pub struct Type; - | --------------- this type doesn't implement the required trait -4 | pub trait Trait { - | --------------- this is the found trait - = note: two types coming from two different versions of the same crate are different types even if they look the same - = help: you can use `cargo tree` to explore your dependency tree"#) - .assert_stderr_contains(r#"note: required by a bound in `do_something`"#) - .assert_stderr_contains(r#" -12 | pub fn do_something(_: X) {} - | ^^^^^ required by this bound in `do_something`"#) - .assert_stderr_contains(r#"error[E0599]: no method named `foo` found for struct `dep_2_reexport::Type` in the current scope - --> multiple-dep-versions.rs:8:10 - | -8 | Type.foo(); - | ^^^ method not found in `Type` - | -note: there are multiple different versions of crate `dependency` in the dependency graph"#) - .assert_stderr_contains(r#" -4 | pub trait Trait { - | ^^^^^^^^^^^^^^^ this is the trait that is needed -5 | fn foo(&self); - | -------------- the method is available for `dep_2_reexport::Type` here - | - ::: multiple-dep-versions.rs:4:18 - | -4 | use dependency::{Trait, do_something}; - | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`"#) - .assert_stderr_contains(r#" -4 | pub trait Trait { - | --------------- this is the trait that was imported"#) - .assert_stderr_contains(r#" -error[E0599]: no function or associated item named `bar` found for struct `dep_2_reexport::Type` in the current scope - --> multiple-dep-versions.rs:9:11 - | -9 | Type::bar(); - | ^^^ function or associated item not found in `Type` - | -note: there are multiple different versions of crate `dependency` in the dependency graph"#) - .assert_stderr_contains(r#" -4 | pub trait Trait { - | ^^^^^^^^^^^^^^^ this is the trait that is needed -5 | fn foo(&self); -6 | fn bar(); - | --------- the associated function is available for `dep_2_reexport::Type` here - | - ::: multiple-dep-versions.rs:4:18 - | -4 | use dependency::{Trait, do_something}; - | ----- `Trait` imported here doesn't correspond to the right version of crate `dependency`"#) - .assert_stderr_contains( - r#" -6 | pub struct OtherType; - | -------------------- this type doesn't implement the required trait"#); + .stderr_utf8(); + + // We don't remap all the paths, so we remap it here. + let mut lines: Vec<_> = out.lines().collect(); + for line in &mut lines { + if line.starts_with(" --> ") { + *line = " --> replaced"; + } + if line.starts_with(" ::: ") { + *line = " ::: replaced"; + } + } + diff() + .expected_file("multiple-dep-versions.stderr") + .actual_text("(rustc)", &lines.join("\n")) + .run(); } -- cgit 1.4.1-3-g733a5 From 2ba7d68011bfcbfb8f5c75d60bd357c0ba0386aa Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 29 Nov 2024 18:41:03 -0500 Subject: Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/tools') diff --git a/src/tools/cargo b/src/tools/cargo index 4c39aaff668..3908f64086a 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 4c39aaff66862cc0da52fe529aa1990bb8bb9a22 +Subproject commit 3908f64086a3d7b9af8d87b4da2bd100776c3e61 -- cgit 1.4.1-3-g733a5 From f5691baba63ac568239b480c1de4a168fb3b6675 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 30 Nov 2024 10:34:38 +0100 Subject: Revert "Auto merge of #133654 - weihanglo:update-cargo, r=weihanglo" This reverts commit 76f3ff605962d7046bc1537597ceed5e12325f54, reversing changes made to 1fc691e6ddc24506b5234d586a5c084eb767f1ad. The new pgo_works test fails when rust is built without profiling support, including in CI on x86_64-gnu-aux. --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/tools') diff --git a/src/tools/cargo b/src/tools/cargo index 3908f64086a..4c39aaff668 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 3908f64086a3d7b9af8d87b4da2bd100776c3e61 +Subproject commit 4c39aaff66862cc0da52fe529aa1990bb8bb9a22 -- cgit 1.4.1-3-g733a5 From ce95a44db65f7f595812a52df6b2f0bc479bd290 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 30 Nov 2024 18:05:48 +0100 Subject: improve TagEncoding::Niche docs and sanity check --- compiler/rustc_abi/src/lib.rs | 24 +++++++++++++++---- compiler/rustc_ty_utils/src/layout/invariant.rs | 16 ++++++++++--- .../fail/enum-untagged-variant-invalid-encoding.rs | 27 ++++++++++++++++++++++ .../enum-untagged-variant-invalid-encoding.stderr | 15 ++++++++++++ 4 files changed, 74 insertions(+), 8 deletions(-) create mode 100644 src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.rs create mode 100644 src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.stderr (limited to 'src/tools') diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 2e51753ede6..7ae8b027e3e 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1215,6 +1215,15 @@ impl Scalar { Scalar::Union { .. } => true, } } + + /// Returns `true` if this is a signed integer scalar + #[inline] + pub fn is_signed(&self) -> bool { + match self.primitive() { + Primitive::Int(_, signed) => signed, + _ => false, + } + } } // NOTE: This struct is generic over the FieldIdx for rust-analyzer usage. @@ -1401,10 +1410,7 @@ impl BackendRepr { #[inline] pub fn is_signed(&self) -> bool { match self { - BackendRepr::Scalar(scal) => match scal.primitive() { - Primitive::Int(_, signed) => signed, - _ => false, - }, + BackendRepr::Scalar(scal) => scal.is_signed(), _ => panic!("`is_signed` on non-scalar ABI {self:?}"), } } @@ -1528,14 +1534,22 @@ pub enum TagEncoding { /// The variant `untagged_variant` contains a niche at an arbitrary /// offset (field `tag_field` of the enum), which for a variant with /// discriminant `d` is set to - /// `(d - niche_variants.start).wrapping_add(niche_start)`. + /// `(d - niche_variants.start).wrapping_add(niche_start)` + /// (this is wrapping arithmetic using the type of the niche field). /// /// For example, `Option<(usize, &T)>` is represented such that /// `None` has a null pointer for the second tuple field, and /// `Some` is the identity function (with a non-null reference). + /// + /// Other variants that are not `untagged_variant` and that are outside the `niche_variants` + /// range cannot be represented; they must be uninhabited. Niche { untagged_variant: VariantIdx, + /// This range *may* contain `untagged_variant`; that is then just a "dead value" and + /// not used to encode anything. niche_variants: RangeInclusive, + /// This is inbounds of the type of the niche field + /// (not sign-extended, i.e., all bits beyond the niche field size are 0). niche_start: u128, }, } diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs index 26ea81daf78..f39b87622f4 100644 --- a/compiler/rustc_ty_utils/src/layout/invariant.rs +++ b/compiler/rustc_ty_utils/src/layout/invariant.rs @@ -1,11 +1,11 @@ use std::assert_matches::assert_matches; -use rustc_abi::{BackendRepr, FieldsShape, Scalar, Size, Variants}; +use rustc_abi::{BackendRepr, FieldsShape, Scalar, Size, TagEncoding, Variants}; use rustc_middle::bug; use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, TyAndLayout}; /// Enforce some basic invariants on layouts. -pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) { +pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) { let tcx = cx.tcx(); // Type-level uninhabitedness should always imply ABI uninhabitedness. @@ -241,7 +241,17 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa check_layout_abi(cx, layout); - if let Variants::Multiple { variants, .. } = &layout.variants { + if let Variants::Multiple { variants, tag, tag_encoding, .. } = &layout.variants { + if let TagEncoding::Niche { niche_start, untagged_variant, niche_variants } = tag_encoding { + let niche_size = tag.size(cx); + assert!(*niche_start <= niche_size.unsigned_int_max()); + for (idx, variant) in variants.iter_enumerated() { + // Ensure all inhabited variants are accounted for. + if !variant.is_uninhabited() { + assert!(idx == *untagged_variant || niche_variants.contains(&idx)); + } + } + } for variant in variants.iter() { // No nested "multiple". assert_matches!(variant.variants, Variants::Single { .. }); diff --git a/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.rs b/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.rs new file mode 100644 index 00000000000..bd02e7f5fb4 --- /dev/null +++ b/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.rs @@ -0,0 +1,27 @@ +// Validity makes this fail at the wrong place. +//@compile-flags: -Zmiri-disable-validation +use std::mem; + +// This enum has untagged variant idx 1, with niche_variants being 0..=2 +// and niche_start being 2. +// That means the untagged variants is in the niche variant range! +// However, using the corresponding value (2+1 = 3) is not a valid encoding of this variant. +#[derive(Copy, Clone, PartialEq)] +enum Foo { + Var1, + Var2(bool), + Var3, +} + +fn main() { + unsafe { + assert!(Foo::Var2(false) == mem::transmute(0u8)); + assert!(Foo::Var2(true) == mem::transmute(1u8)); + assert!(Foo::Var1 == mem::transmute(2u8)); + assert!(Foo::Var3 == mem::transmute(4u8)); + + let invalid: Foo = mem::transmute(3u8); + assert!(matches!(invalid, Foo::Var2(_))); + //~^ ERROR: invalid tag + } +} diff --git a/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.stderr b/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.stderr new file mode 100644 index 00000000000..759dbc36380 --- /dev/null +++ b/src/tools/miri/tests/fail/enum-untagged-variant-invalid-encoding.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: enum value has invalid tag: 0x03 + --> tests/fail/enum-untagged-variant-invalid-encoding.rs:LL:CC + | +LL | assert!(matches!(invalid, Foo::Var2(_))); + | ^^^^^^^ enum value has invalid tag: 0x03 + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at tests/fail/enum-untagged-variant-invalid-encoding.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + -- cgit 1.4.1-3-g733a5 From 7ced18f329470e5dbdbee54d273193d19e3b43f4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 28 Nov 2024 12:47:18 -0800 Subject: Eliminate magic numbers from expression precedence --- compiler/rustc_ast/src/ast.rs | 22 +++---- compiler/rustc_ast/src/util/parser.rs | 74 +++++++++++++++------- compiler/rustc_ast_pretty/src/pprust/state/expr.rs | 49 +++++++------- compiler/rustc_errors/src/diagnostic_impls.rs | 7 ++ compiler/rustc_hir/src/hir.rs | 18 +++--- compiler/rustc_hir_pretty/src/lib.rs | 37 +++++------ compiler/rustc_hir_typeck/src/callee.rs | 4 +- compiler/rustc_hir_typeck/src/cast.rs | 3 +- .../rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 10 +-- compiler/rustc_parse/src/errors.rs | 3 +- compiler/rustc_parse/src/parser/expr.rs | 8 +-- compiler/rustc_parse/src/parser/pat.rs | 16 ++--- src/tools/clippy/clippy_lints/src/dereference.rs | 28 ++++---- .../clippy_lints/src/loops/single_element_loop.rs | 4 +- .../clippy_lints/src/matches/manual_utils.rs | 4 +- src/tools/clippy/clippy_lints/src/neg_multiply.rs | 4 +- .../clippy/clippy_lints/src/redundant_slicing.rs | 4 +- .../transmutes_expressible_as_ptr_casts.rs | 5 +- 18 files changed, 162 insertions(+), 138 deletions(-) (limited to 'src/tools') diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 56b20e0ad89..14205f66491 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -39,9 +39,7 @@ pub use crate::format::*; use crate::ptr::P; use crate::token::{self, CommentKind, Delimiter}; use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream}; -use crate::util::parser::{ - AssocOp, PREC_CLOSURE, PREC_JUMP, PREC_PREFIX, PREC_RANGE, PREC_UNAMBIGUOUS, -}; +use crate::util::parser::{AssocOp, ExprPrecedence}; /// A "Label" is an identifier of some point in sources, /// e.g. in the following code: @@ -1317,29 +1315,29 @@ impl Expr { Some(P(Ty { kind, id: self.id, span: self.span, tokens: None })) } - pub fn precedence(&self) -> i8 { + pub fn precedence(&self) -> ExprPrecedence { match self.kind { - ExprKind::Closure(..) => PREC_CLOSURE, + ExprKind::Closure(..) => ExprPrecedence::Closure, ExprKind::Break(..) | ExprKind::Continue(..) | ExprKind::Ret(..) | ExprKind::Yield(..) | ExprKind::Yeet(..) - | ExprKind::Become(..) => PREC_JUMP, + | ExprKind::Become(..) => ExprPrecedence::Jump, // `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to // parse, instead of parsing as `(x .. x) = x`. Giving `Range` a lower precedence // ensures that `pprust` will add parentheses in the right places to get the desired // parse. - ExprKind::Range(..) => PREC_RANGE, + ExprKind::Range(..) => ExprPrecedence::Range, // Binop-like expr kinds, handled by `AssocOp`. - ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence() as i8, - ExprKind::Cast(..) => AssocOp::As.precedence() as i8, + ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence(), + ExprKind::Cast(..) => ExprPrecedence::Cast, ExprKind::Assign(..) | - ExprKind::AssignOp(..) => AssocOp::Assign.precedence() as i8, + ExprKind::AssignOp(..) => ExprPrecedence::Assign, // Unary, prefix ExprKind::AddrOf(..) @@ -1348,7 +1346,7 @@ impl Expr { // need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b` // but we need to print `(let _ = a) < b` as-is with parens. | ExprKind::Let(..) - | ExprKind::Unary(..) => PREC_PREFIX, + | ExprKind::Unary(..) => ExprPrecedence::Prefix, // Never need parens ExprKind::Array(_) @@ -1381,7 +1379,7 @@ impl Expr { | ExprKind::Underscore | ExprKind::While(..) | ExprKind::Err(_) - | ExprKind::Dummy => PREC_UNAMBIGUOUS, + | ExprKind::Dummy => ExprPrecedence::Unambiguous, } } diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs index 07c72141cc9..e88bf27021a 100644 --- a/compiler/rustc_ast/src/util/parser.rs +++ b/compiler/rustc_ast/src/util/parser.rs @@ -128,21 +128,21 @@ impl AssocOp { } /// Gets the precedence of this operator - pub fn precedence(&self) -> usize { + pub fn precedence(&self) -> ExprPrecedence { use AssocOp::*; match *self { - As => 14, - Multiply | Divide | Modulus => 13, - Add | Subtract => 12, - ShiftLeft | ShiftRight => 11, - BitAnd => 10, - BitXor => 9, - BitOr => 8, - Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => 7, - LAnd => 6, - LOr => 5, - DotDot | DotDotEq => 4, - Assign | AssignOp(_) => 2, + As => ExprPrecedence::Cast, + Multiply | Divide | Modulus => ExprPrecedence::Product, + Add | Subtract => ExprPrecedence::Sum, + ShiftLeft | ShiftRight => ExprPrecedence::Shift, + BitAnd => ExprPrecedence::BitAnd, + BitXor => ExprPrecedence::BitXor, + BitOr => ExprPrecedence::BitOr, + Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => ExprPrecedence::Compare, + LAnd => ExprPrecedence::LAnd, + LOr => ExprPrecedence::LOr, + DotDot | DotDotEq => ExprPrecedence::Range, + Assign | AssignOp(_) => ExprPrecedence::Assign, } } @@ -229,16 +229,44 @@ impl AssocOp { } } -pub const PREC_CLOSURE: i8 = -40; -pub const PREC_JUMP: i8 = -30; -pub const PREC_RANGE: i8 = -10; -// The range 2..=14 is reserved for AssocOp binary operator precedences. -pub const PREC_PREFIX: i8 = 50; -pub const PREC_UNAMBIGUOUS: i8 = 60; +#[derive(Clone, Copy, PartialEq, PartialOrd)] +pub enum ExprPrecedence { + Closure, + // return, break, yield + Jump, + // = += -= *= /= %= &= |= ^= <<= >>= + Assign, + // .. ..= + Range, + // || + LOr, + // && + LAnd, + // == != < > <= >= + Compare, + // | + BitOr, + // ^ + BitXor, + // & + BitAnd, + // << >> + Shift, + // + - + Sum, + // * / % + Product, + // as + Cast, + // unary - * ! & &mut + Prefix, + // paths, loops, function calls, array indexing, field expressions, method calls + Unambiguous, +} /// In `let p = e`, operators with precedence `<=` this one requires parentheses in `e`. -pub fn prec_let_scrutinee_needs_par() -> usize { - AssocOp::LAnd.precedence() +pub fn prec_let_scrutinee_needs_par() -> ExprPrecedence { + ExprPrecedence::LAnd } /// Suppose we have `let _ = e` and the `order` of `e`. @@ -246,8 +274,8 @@ pub fn prec_let_scrutinee_needs_par() -> usize { /// /// Conversely, suppose that we have `(let _ = a) OP b` and `order` is that of `OP`. /// Can we print this as `let _ = a OP b`? -pub fn needs_par_as_let_scrutinee(order: i8) -> bool { - order <= prec_let_scrutinee_needs_par() as i8 +pub fn needs_par_as_let_scrutinee(order: ExprPrecedence) -> bool { + order <= prec_let_scrutinee_needs_par() } /// Expressions that syntactically contain an "exterior" struct literal i.e., not surrounded by any diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 679f7c4fb59..c239cb249c3 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -5,7 +5,7 @@ use itertools::{Itertools, Position}; use rustc_ast::ptr::P; use rustc_ast::util::classify; use rustc_ast::util::literal::escape_byte_str_symbol; -use rustc_ast::util::parser::{self, AssocOp, Fixity}; +use rustc_ast::util::parser::{self, AssocOp, ExprPrecedence, Fixity}; use rustc_ast::{ self as ast, BlockCheckMode, FormatAlignment, FormatArgPosition, FormatArgsPiece, FormatCount, FormatDebugHex, FormatSign, FormatTrait, token, @@ -214,7 +214,7 @@ impl<'a> State<'a> { fn print_expr_call(&mut self, func: &ast::Expr, args: &[P], fixup: FixupContext) { let needs_paren = match func.kind { ast::ExprKind::Field(..) => true, - _ => func.precedence() < parser::PREC_UNAMBIGUOUS, + _ => func.precedence() < ExprPrecedence::Unambiguous, }; // Independent of parenthesization related to precedence, we must @@ -256,7 +256,7 @@ impl<'a> State<'a> { // a statement containing an expression. self.print_expr_cond_paren( receiver, - receiver.precedence() < parser::PREC_UNAMBIGUOUS, + receiver.precedence() < ExprPrecedence::Unambiguous, fixup, ); @@ -276,7 +276,7 @@ impl<'a> State<'a> { fixup: FixupContext, ) { let assoc_op = AssocOp::from_ast_binop(op.node); - let binop_prec = assoc_op.precedence() as i8; + let binop_prec = assoc_op.precedence(); let left_prec = lhs.precedence(); let right_prec = rhs.precedence(); @@ -317,7 +317,7 @@ impl<'a> State<'a> { self.word(op.as_str()); self.print_expr_cond_paren( expr, - expr.precedence() < parser::PREC_PREFIX, + expr.precedence() < ExprPrecedence::Prefix, fixup.subsequent_subexpression(), ); } @@ -339,7 +339,7 @@ impl<'a> State<'a> { } self.print_expr_cond_paren( expr, - expr.precedence() < parser::PREC_PREFIX, + expr.precedence() < ExprPrecedence::Prefix, fixup.subsequent_subexpression(), ); } @@ -423,10 +423,9 @@ impl<'a> State<'a> { self.print_token_literal(lit, expr.span) } ast::ExprKind::Cast(expr, ty) => { - let prec = AssocOp::As.precedence() as i8; self.print_expr_cond_paren( expr, - expr.precedence() < prec, + expr.precedence() < ExprPrecedence::Cast, fixup.leftmost_subexpression(), ); self.space(); @@ -503,7 +502,7 @@ impl<'a> State<'a> { MatchKind::Postfix => { self.print_expr_cond_paren( expr, - expr.precedence() < parser::PREC_UNAMBIGUOUS, + expr.precedence() < ExprPrecedence::Unambiguous, fixup, ); self.word_nbsp(".match"); @@ -567,31 +566,31 @@ impl<'a> State<'a> { ast::ExprKind::Await(expr, _) => { self.print_expr_cond_paren( expr, - expr.precedence() < parser::PREC_UNAMBIGUOUS, + expr.precedence() < ExprPrecedence::Unambiguous, fixup, ); self.word(".await"); } ast::ExprKind::Assign(lhs, rhs, _) => { - let prec = AssocOp::Assign.precedence() as i8; self.print_expr_cond_paren( lhs, - lhs.precedence() <= prec, + // Ranges are allowed on the right-hand side of assignment, + // but not the left. `(a..b) = c` needs parentheses. + lhs.precedence() <= ExprPrecedence::Range, fixup.leftmost_subexpression(), ); self.space(); self.word_space("="); self.print_expr_cond_paren( rhs, - rhs.precedence() < prec, + rhs.precedence() < ExprPrecedence::Assign, fixup.subsequent_subexpression(), ); } ast::ExprKind::AssignOp(op, lhs, rhs) => { - let prec = AssocOp::Assign.precedence() as i8; self.print_expr_cond_paren( lhs, - lhs.precedence() <= prec, + lhs.precedence() <= ExprPrecedence::Range, fixup.leftmost_subexpression(), ); self.space(); @@ -599,14 +598,14 @@ impl<'a> State<'a> { self.word_space("="); self.print_expr_cond_paren( rhs, - rhs.precedence() < prec, + rhs.precedence() < ExprPrecedence::Assign, fixup.subsequent_subexpression(), ); } ast::ExprKind::Field(expr, ident) => { self.print_expr_cond_paren( expr, - expr.precedence() < parser::PREC_UNAMBIGUOUS, + expr.precedence() < ExprPrecedence::Unambiguous, fixup, ); self.word("."); @@ -615,7 +614,7 @@ impl<'a> State<'a> { ast::ExprKind::Index(expr, index, _) => { self.print_expr_cond_paren( expr, - expr.precedence() < parser::PREC_UNAMBIGUOUS, + expr.precedence() < ExprPrecedence::Unambiguous, fixup.leftmost_subexpression(), ); self.word("["); @@ -627,7 +626,7 @@ impl<'a> State<'a> { // than `Assign`, but `x .. x = x` gives a parse error instead of `x .. (x = x)`. // Here we use a fake precedence value so that any child with lower precedence than // a "normal" binop gets parenthesized. (`LOr` is the lowest-precedence binop.) - let fake_prec = AssocOp::LOr.precedence() as i8; + let fake_prec = ExprPrecedence::LOr; if let Some(e) = start { self.print_expr_cond_paren( e, @@ -662,7 +661,7 @@ impl<'a> State<'a> { expr, // Parenthesize if required by precedence, or in the // case of `break 'inner: loop { break 'inner 1 } + 1` - expr.precedence() < parser::PREC_JUMP + expr.precedence() < ExprPrecedence::Jump || (opt_label.is_none() && classify::leading_labeled_expr(expr)), fixup.subsequent_subexpression(), ); @@ -681,7 +680,7 @@ impl<'a> State<'a> { self.word(" "); self.print_expr_cond_paren( expr, - expr.precedence() < parser::PREC_JUMP, + expr.precedence() < ExprPrecedence::Jump, fixup.subsequent_subexpression(), ); } @@ -694,7 +693,7 @@ impl<'a> State<'a> { self.word(" "); self.print_expr_cond_paren( expr, - expr.precedence() < parser::PREC_JUMP, + expr.precedence() < ExprPrecedence::Jump, fixup.subsequent_subexpression(), ); } @@ -704,7 +703,7 @@ impl<'a> State<'a> { self.word(" "); self.print_expr_cond_paren( result, - result.precedence() < parser::PREC_JUMP, + result.precedence() < ExprPrecedence::Jump, fixup.subsequent_subexpression(), ); } @@ -758,13 +757,13 @@ impl<'a> State<'a> { self.space(); self.print_expr_cond_paren( expr, - expr.precedence() < parser::PREC_JUMP, + expr.precedence() < ExprPrecedence::Jump, fixup.subsequent_subexpression(), ); } } ast::ExprKind::Try(e) => { - self.print_expr_cond_paren(e, e.precedence() < parser::PREC_UNAMBIGUOUS, fixup); + self.print_expr_cond_paren(e, e.precedence() < ExprPrecedence::Unambiguous, fixup); self.word("?") } ast::ExprKind::TryBlock(blk) => { diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 798668b8bc1..b4510371323 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -6,6 +6,7 @@ use std::path::{Path, PathBuf}; use std::process::ExitStatus; use rustc_abi::TargetDataLayoutErrors; +use rustc_ast::util::parser::ExprPrecedence; use rustc_ast_pretty::pprust; use rustc_macros::Subdiagnostic; use rustc_span::Span; @@ -298,6 +299,12 @@ impl IntoDiagArg for hir::def::Namespace { } } +impl IntoDiagArg for ExprPrecedence { + fn into_diag_arg(self) -> DiagArgValue { + DiagArgValue::Number(self as i32) + } +} + #[derive(Clone)] pub struct DiagSymbolList(Vec); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 12dec75e65c..f13289ac48f 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1,7 +1,7 @@ use std::fmt; use rustc_abi::ExternAbi; -use rustc_ast::util::parser::{AssocOp, PREC_CLOSURE, PREC_JUMP, PREC_PREFIX, PREC_UNAMBIGUOUS}; +use rustc_ast::util::parser::{AssocOp, ExprPrecedence}; use rustc_ast::{ self as ast, Attribute, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece, IntTy, Label, LitKind, TraitObjectSyntax, UintTy, @@ -1708,22 +1708,22 @@ pub struct Expr<'hir> { } impl Expr<'_> { - pub fn precedence(&self) -> i8 { + pub fn precedence(&self) -> ExprPrecedence { match self.kind { - ExprKind::Closure { .. } => PREC_CLOSURE, + ExprKind::Closure { .. } => ExprPrecedence::Closure, ExprKind::Break(..) | ExprKind::Continue(..) | ExprKind::Ret(..) | ExprKind::Yield(..) - | ExprKind::Become(..) => PREC_JUMP, + | ExprKind::Become(..) => ExprPrecedence::Jump, // Binop-like expr kinds, handled by `AssocOp`. - ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence() as i8, - ExprKind::Cast(..) => AssocOp::As.precedence() as i8, + ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence(), + ExprKind::Cast(..) => ExprPrecedence::Cast, ExprKind::Assign(..) | - ExprKind::AssignOp(..) => AssocOp::Assign.precedence() as i8, + ExprKind::AssignOp(..) => ExprPrecedence::Assign, // Unary, prefix ExprKind::AddrOf(..) @@ -1732,7 +1732,7 @@ impl Expr<'_> { // need parens sometimes. E.g. we can print `(let _ = a) && b` as `let _ = a && b` // but we need to print `(let _ = a) < b` as-is with parens. | ExprKind::Let(..) - | ExprKind::Unary(..) => PREC_PREFIX, + | ExprKind::Unary(..) => ExprPrecedence::Prefix, // Never need parens ExprKind::Array(_) @@ -1753,7 +1753,7 @@ impl Expr<'_> { | ExprKind::Struct(..) | ExprKind::Tup(_) | ExprKind::Type(..) - | ExprKind::Err(_) => PREC_UNAMBIGUOUS, + | ExprKind::Err(_) => ExprPrecedence::Unambiguous, ExprKind::DropTemps(ref expr, ..) => expr.precedence(), } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 880e527a2bb..9099e14b330 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -10,7 +10,7 @@ use std::cell::Cell; use std::vec; use rustc_abi::ExternAbi; -use rustc_ast::util::parser::{self, AssocOp, Fixity}; +use rustc_ast::util::parser::{self, AssocOp, ExprPrecedence, Fixity}; use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent}; use rustc_ast_pretty::pp::{self, Breaks}; use rustc_ast_pretty::pprust::{Comments, PrintState}; @@ -1134,7 +1134,7 @@ impl<'a> State<'a> { fn print_expr_call(&mut self, func: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { let needs_paren = match func.kind { hir::ExprKind::Field(..) => true, - _ => func.precedence() < parser::PREC_UNAMBIGUOUS, + _ => func.precedence() < ExprPrecedence::Unambiguous, }; self.print_expr_cond_paren(func, needs_paren); @@ -1148,7 +1148,7 @@ impl<'a> State<'a> { args: &[hir::Expr<'_>], ) { let base_args = args; - self.print_expr_cond_paren(receiver, receiver.precedence() < parser::PREC_UNAMBIGUOUS); + self.print_expr_cond_paren(receiver, receiver.precedence() < ExprPrecedence::Unambiguous); self.word("."); self.print_ident(segment.ident); @@ -1162,7 +1162,7 @@ impl<'a> State<'a> { fn print_expr_binary(&mut self, op: hir::BinOp, lhs: &hir::Expr<'_>, rhs: &hir::Expr<'_>) { let assoc_op = AssocOp::from_ast_binop(op.node); - let binop_prec = assoc_op.precedence() as i8; + let binop_prec = assoc_op.precedence(); let left_prec = lhs.precedence(); let right_prec = rhs.precedence(); @@ -1193,7 +1193,7 @@ impl<'a> State<'a> { fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr<'_>) { self.word(op.as_str()); - self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_PREFIX) + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Prefix); } fn print_expr_addr_of( @@ -1210,7 +1210,7 @@ impl<'a> State<'a> { self.print_mutability(mutability, true); } } - self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_PREFIX) + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Prefix); } fn print_literal(&mut self, lit: &hir::Lit) { @@ -1348,8 +1348,7 @@ impl<'a> State<'a> { self.print_literal(lit); } hir::ExprKind::Cast(expr, ty) => { - let prec = AssocOp::As.precedence() as i8; - self.print_expr_cond_paren(expr, expr.precedence() < prec); + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Cast); self.space(); self.word_space("as"); self.print_type(ty); @@ -1450,27 +1449,25 @@ impl<'a> State<'a> { self.print_block(blk); } hir::ExprKind::Assign(lhs, rhs, _) => { - let prec = AssocOp::Assign.precedence() as i8; - self.print_expr_cond_paren(lhs, lhs.precedence() <= prec); + self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign); self.space(); self.word_space("="); - self.print_expr_cond_paren(rhs, rhs.precedence() < prec); + self.print_expr_cond_paren(rhs, rhs.precedence() < ExprPrecedence::Assign); } hir::ExprKind::AssignOp(op, lhs, rhs) => { - let prec = AssocOp::Assign.precedence() as i8; - self.print_expr_cond_paren(lhs, lhs.precedence() <= prec); + self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign); self.space(); self.word(op.node.as_str()); self.word_space("="); - self.print_expr_cond_paren(rhs, rhs.precedence() < prec); + self.print_expr_cond_paren(rhs, rhs.precedence() < ExprPrecedence::Assign); } hir::ExprKind::Field(expr, ident) => { - self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_UNAMBIGUOUS); + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Unambiguous); self.word("."); self.print_ident(ident); } hir::ExprKind::Index(expr, index, _) => { - self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_UNAMBIGUOUS); + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Unambiguous); self.word("["); self.print_expr(index); self.word("]"); @@ -1484,7 +1481,7 @@ impl<'a> State<'a> { } if let Some(expr) = opt_expr { self.space(); - self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_JUMP); + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump); } } hir::ExprKind::Continue(destination) => { @@ -1498,13 +1495,13 @@ impl<'a> State<'a> { self.word("return"); if let Some(expr) = result { self.word(" "); - self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_JUMP); + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump); } } hir::ExprKind::Become(result) => { self.word("become"); self.word(" "); - self.print_expr_cond_paren(result, result.precedence() < parser::PREC_JUMP); + self.print_expr_cond_paren(result, result.precedence() < ExprPrecedence::Jump); } hir::ExprKind::InlineAsm(asm) => { self.word("asm!"); @@ -1529,7 +1526,7 @@ impl<'a> State<'a> { } hir::ExprKind::Yield(expr, _) => { self.word_space("yield"); - self.print_expr_cond_paren(expr, expr.precedence() < parser::PREC_JUMP); + self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump); } hir::ExprKind::Err(_) => { self.popen(); diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index a92482e6a0e..ee44c799757 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -1,6 +1,6 @@ use std::iter; -use rustc_ast::util::parser::PREC_UNAMBIGUOUS; +use rustc_ast::util::parser::ExprPrecedence; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey}; use rustc_hir::def::{self, CtorKind, Namespace, Res}; use rustc_hir::def_id::DefId; @@ -606,7 +606,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if let Ok(rest_snippet) = rest_snippet { - let sugg = if callee_expr.precedence() >= PREC_UNAMBIGUOUS { + let sugg = if callee_expr.precedence() >= ExprPrecedence::Unambiguous { vec![ (up_to_rcvr_span, "".to_string()), (rest_span, format!(".{}({rest_snippet}", segment.ident)), diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 0c3f21d540d..80b91c21598 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -28,6 +28,7 @@ //! expression, `e as U2` is not necessarily so (in fact it will only be valid if //! `U1` coerces to `U2`). +use rustc_ast::util::parser::ExprPrecedence; use rustc_data_structures::fx::FxHashSet; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, ErrorGuaranteed}; @@ -1108,7 +1109,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { fn lossy_provenance_ptr2int_lint(&self, fcx: &FnCtxt<'a, 'tcx>, t_c: ty::cast::IntTy) { let expr_prec = self.expr.precedence(); - let needs_parens = expr_prec < rustc_ast::util::parser::PREC_UNAMBIGUOUS; + let needs_parens = expr_prec < ExprPrecedence::Unambiguous; let needs_cast = !matches!(t_c, ty::cast::IntTy::U(ty::UintTy::Usize)); let cast_span = self.expr_span.shrink_to_hi().to(self.cast_span); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index b493a61b9f4..61260dbd16c 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -2,7 +2,7 @@ use core::cmp::min; use core::iter; use hir::def_id::LocalDefId; -use rustc_ast::util::parser::PREC_UNAMBIGUOUS; +use rustc_ast::util::parser::ExprPrecedence; use rustc_data_structures::packed::Pu128; use rustc_errors::{Applicability, Diag, MultiSpan}; use rustc_hir as hir; @@ -398,7 +398,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // so we remove the user's `clone` call. { vec![(receiver_method.ident.span, conversion_method.name.to_string())] - } else if expr.precedence() < PREC_UNAMBIGUOUS { + } else if expr.precedence() < ExprPrecedence::Unambiguous { vec![ (expr.span.shrink_to_lo(), "(".to_string()), (expr.span.shrink_to_hi(), format!(").{}()", conversion_method.name)), @@ -1376,7 +1376,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let span = expr.span.find_oldest_ancestor_in_same_ctxt(); - let mut sugg = if expr.precedence() >= PREC_UNAMBIGUOUS { + let mut sugg = if expr.precedence() >= ExprPrecedence::Unambiguous { vec![(span.shrink_to_hi(), ".into()".to_owned())] } else { vec![ @@ -3000,7 +3000,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "change the type of the numeric literal from `{checked_ty}` to `{expected_ty}`", ); - let close_paren = if expr.precedence() < PREC_UNAMBIGUOUS { + let close_paren = if expr.precedence() < ExprPrecedence::Unambiguous { sugg.push((expr.span.shrink_to_lo(), "(".to_string())); ")" } else { @@ -3025,7 +3025,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let len = src.trim_end_matches(&checked_ty.to_string()).len(); expr.span.with_lo(expr.span.lo() + BytePos(len as u32)) }, - if expr.precedence() < PREC_UNAMBIGUOUS { + if expr.precedence() < ExprPrecedence::Unambiguous { // Readd `)` format!("{expected_ty})") } else { diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 91e8ba2e1f9..2579e4c1f25 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -3,6 +3,7 @@ use std::borrow::Cow; use rustc_ast::token::Token; +use rustc_ast::util::parser::ExprPrecedence; use rustc_ast::{Path, Visibility}; use rustc_errors::codes::*; use rustc_errors::{ @@ -2686,7 +2687,7 @@ pub(crate) struct UnexpectedExpressionInPattern { /// Was a `RangePatternBound` expected? pub is_bound: bool, /// The unexpected expr's precedence (used in match arm guard suggestions). - pub expr_precedence: i8, + pub expr_precedence: ExprPrecedence, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index a3b0076f5ad..8d16d44b0a2 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -10,7 +10,7 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; use rustc_ast::util::case::Case; use rustc_ast::util::classify; -use rustc_ast::util::parser::{AssocOp, Fixity, prec_let_scrutinee_needs_par}; +use rustc_ast::util::parser::{AssocOp, ExprPrecedence, Fixity, prec_let_scrutinee_needs_par}; use rustc_ast::visit::{Visitor, walk_expr}; use rustc_ast::{ self as ast, AnonConst, Arm, AttrStyle, AttrVec, BinOp, BinOpKind, BlockCheckMode, CaptureBy, @@ -128,7 +128,7 @@ impl<'a> Parser<'a> { /// followed by a subexpression (e.g. `1 + 2`). pub(super) fn parse_expr_assoc_with( &mut self, - min_prec: Bound, + min_prec: Bound, attrs: AttrWrapper, ) -> PResult<'a, (P, bool)> { let lhs = if self.token.is_range_separator() { @@ -144,7 +144,7 @@ impl<'a> Parser<'a> { /// was actually parsed. pub(super) fn parse_expr_assoc_rest_with( &mut self, - min_prec: Bound, + min_prec: Bound, starts_stmt: bool, mut lhs: P, ) -> PResult<'a, (P, bool)> { @@ -455,7 +455,7 @@ impl<'a> Parser<'a> { /// The other two variants are handled in `parse_prefix_range_expr` below. fn parse_expr_range( &mut self, - prec: usize, + prec: ExprPrecedence, lhs: P, op: AssocOp, cur_op_span: Span, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 32efe9af0c9..e08b925f008 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -3,12 +3,11 @@ use std::ops::Bound; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::ptr::P; use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token}; -use rustc_ast::util::parser::AssocOp; +use rustc_ast::util::parser::ExprPrecedence; use rustc_ast::visit::{self, Visitor}; use rustc_ast::{ - self as ast, Arm, AttrVec, BinOpKind, BindingMode, ByRef, Expr, ExprKind, LocalKind, MacCall, - Mutability, Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, Stmt, - StmtKind, + self as ast, Arm, AttrVec, BindingMode, ByRef, Expr, ExprKind, LocalKind, MacCall, Mutability, + Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, Stmt, StmtKind, }; use rustc_ast_pretty::pprust; use rustc_errors::{Applicability, Diag, DiagArgValue, PResult, StashKey}; @@ -548,10 +547,7 @@ impl<'a> Parser<'a> { // HACK: a neater way would be preferable. let expr = match &err.args["expr_precedence"] { DiagArgValue::Number(expr_precedence) => { - if *expr_precedence - <= AssocOp::from_ast_binop(BinOpKind::Eq).precedence() - as i32 - { + if *expr_precedence <= ExprPrecedence::Compare as i32 { format!("({expr})") } else { format!("{expr}") @@ -573,9 +569,7 @@ impl<'a> Parser<'a> { } Some(guard) => { // Are parentheses required around the old guard? - let wrap_guard = guard.precedence() - <= AssocOp::from_ast_binop(BinOpKind::And).precedence() - as i8; + let wrap_guard = guard.precedence() <= ExprPrecedence::LAnd; err.subdiagnostic( UnexpectedExpressionInPatternSugg::UpdateGuard { diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index b1d192adff9..c449a1a875b 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -7,7 +7,7 @@ use clippy_utils::{ peel_middle_ty_refs, }; use core::mem; -use rustc_ast::util::parser::{PREC_PREFIX, PREC_UNAMBIGUOUS}; +use rustc_ast::util::parser::ExprPrecedence; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; @@ -963,7 +963,7 @@ fn report<'tcx>( // expr_str (the suggestion) is never shown if is_final_ufcs is true, since it's // `expr.kind == ExprKind::Call`. Therefore, this is, afaik, always unnecessary. /* - expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence() < PREC_PREFIX { + expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence() < ExprPrecedence::Prefix { Cow::Owned(format!("({expr_str})")) } else { expr_str @@ -999,13 +999,13 @@ fn report<'tcx>( data.first_expr.span, state.msg, |diag| { - let (precedence, calls_field) = match cx.tcx.parent_hir_node(data.first_expr.hir_id) { + let needs_paren = match cx.tcx.parent_hir_node(data.first_expr.hir_id) { Node::Expr(e) => match e.kind { - ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => (0, false), - ExprKind::Call(..) => (PREC_UNAMBIGUOUS, matches!(expr.kind, ExprKind::Field(..))), - _ => (e.precedence(), false), + ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => false, + ExprKind::Call(..) => expr.precedence() < ExprPrecedence::Unambiguous || matches!(expr.kind, ExprKind::Field(..)), + _ => expr.precedence() < e.precedence(), }, - _ => (0, false), + _ => false, }; let is_in_tuple = matches!( get_parent_expr(cx, data.first_expr), @@ -1016,7 +1016,7 @@ fn report<'tcx>( ); let sugg = if !snip_is_macro - && (calls_field || expr.precedence() < precedence) + && needs_paren && !has_enclosing_paren(&snip) && !is_in_tuple { @@ -1049,16 +1049,16 @@ fn report<'tcx>( } } - let (prefix, precedence) = match mutability { + let (prefix, needs_paren) = match mutability { Some(mutability) if !ty.is_ref() => { let prefix = match mutability { Mutability::Not => "&", Mutability::Mut => "&mut ", }; - (prefix, PREC_PREFIX) + (prefix, expr.precedence() < ExprPrecedence::Prefix) }, - None if !ty.is_ref() && data.adjusted_ty.is_ref() => ("&", 0), - _ => ("", 0), + None if !ty.is_ref() && data.adjusted_ty.is_ref() => ("&", false), + _ => ("", false), }; span_lint_hir_and_then( cx, @@ -1070,7 +1070,7 @@ fn report<'tcx>( let mut app = Applicability::MachineApplicable; let (snip, snip_is_macro) = snippet_with_context(cx, expr.span, data.first_expr.span.ctxt(), "..", &mut app); - let sugg = if !snip_is_macro && expr.precedence() < precedence && !has_enclosing_paren(&snip) { + let sugg = if !snip_is_macro && needs_paren && !has_enclosing_paren(&snip) { format!("{prefix}({snip})") } else { format!("{prefix}{snip}") @@ -1157,7 +1157,7 @@ impl<'tcx> Dereferencing<'tcx> { }, Some(parent) if !parent.span.from_expansion() => { // Double reference might be needed at this point. - if parent.precedence() == PREC_UNAMBIGUOUS { + if parent.precedence() == ExprPrecedence::Unambiguous { // Parentheses would be needed here, don't lint. *outer_pat = None; } else { diff --git a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs index 35dc8e9aa4e..12719c4f94b 100644 --- a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::{indent_of, snippet, snippet_with_applicability}; use clippy_utils::visitors::contains_break_or_continue; use rustc_ast::Mutability; -use rustc_ast::util::parser::PREC_PREFIX; +use rustc_ast::util::parser::ExprPrecedence; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, Pat, PatKind, is_range_literal}; use rustc_lint::LateContext; @@ -84,7 +84,7 @@ pub(super) fn check<'tcx>( if !prefix.is_empty() && ( // Precedence of internal expression is less than or equal to precedence of `&expr`. - arg_expression.precedence() <= PREC_PREFIX || is_range_literal(arg_expression) + arg_expression.precedence() <= ExprPrecedence::Prefix || is_range_literal(arg_expression) ) { arg_snip = format!("({arg_snip})").into(); diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs index 9c6df4d8ac0..bac5cf88cfb 100644 --- a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs +++ b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs @@ -7,7 +7,7 @@ use clippy_utils::{ CaptureKind, can_move_expr_to_closure, is_else_clause, is_lint_allowed, is_res_lang_ctor, path_res, path_to_local_id, peel_blocks, peel_hir_expr_refs, peel_hir_expr_while, }; -use rustc_ast::util::parser::PREC_UNAMBIGUOUS; +use rustc_ast::util::parser::ExprPrecedence; use rustc_errors::Applicability; use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_hir::def::Res; @@ -117,7 +117,7 @@ where // it's being passed by value. let scrutinee = peel_hir_expr_refs(scrutinee).0; let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app); - let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence() < PREC_UNAMBIGUOUS { + let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence() < ExprPrecedence::Unambiguous { format!("({scrutinee_str})") } else { scrutinee_str.into() diff --git a/src/tools/clippy/clippy_lints/src/neg_multiply.rs b/src/tools/clippy/clippy_lints/src/neg_multiply.rs index a0ba2aaf552..429afff9b66 100644 --- a/src/tools/clippy/clippy_lints/src/neg_multiply.rs +++ b/src/tools/clippy/clippy_lints/src/neg_multiply.rs @@ -2,7 +2,7 @@ use clippy_utils::consts::{self, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_context; use clippy_utils::sugg::has_enclosing_paren; -use rustc_ast::util::parser::PREC_PREFIX; +use rustc_ast::util::parser::ExprPrecedence; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; @@ -58,7 +58,7 @@ fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) { { let mut applicability = Applicability::MachineApplicable; let (snip, from_macro) = snippet_with_context(cx, exp.span, span.ctxt(), "..", &mut applicability); - let suggestion = if !from_macro && exp.precedence() < PREC_PREFIX && !has_enclosing_paren(&snip) { + let suggestion = if !from_macro && exp.precedence() < ExprPrecedence::Prefix && !has_enclosing_paren(&snip) { format!("-({snip})") } else { format!("-{snip}") diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs index 79baa914b03..8e3472b1b5a 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::is_type_lang_item; use clippy_utils::{get_parent_expr, peel_middle_ty_refs}; -use rustc_ast::util::parser::PREC_PREFIX; +use rustc_ast::util::parser::ExprPrecedence; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability}; use rustc_lint::{LateContext, LateLintPass, Lint}; @@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing { let (expr_ty, expr_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(expr)); let (indexed_ty, indexed_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(indexed)); let parent_expr = get_parent_expr(cx, expr); - let needs_parens_for_prefix = parent_expr.is_some_and(|parent| parent.precedence() > PREC_PREFIX); + let needs_parens_for_prefix = parent_expr.is_some_and(|parent| parent.precedence() > ExprPrecedence::Prefix); if expr_ty == indexed_ty { if expr_ref_count > indexed_ref_count { diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs index 8d71036084d..0d5cf45a5e6 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs @@ -1,7 +1,7 @@ use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::sugg::Sugg; -use rustc_ast::util::parser::AssocOp; +use rustc_ast::util::parser::ExprPrecedence; use rustc_errors::Applicability; use rustc_hir::{Expr, Node}; use rustc_hir_typeck::cast::check_cast; @@ -44,8 +44,7 @@ pub(super) fn check<'tcx>( }; if let Node::Expr(parent) = cx.tcx.parent_hir_node(e.hir_id) - && parent.precedence() - > i8::try_from(AssocOp::As.precedence()).expect("AssocOp always returns a precedence < 128") + && parent.precedence() > ExprPrecedence::Cast { sugg = format!("({sugg})"); } -- cgit 1.4.1-3-g733a5 From 374397f1bbfe3d3f13b3fc4d0c4728ac5cfdfcac Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Thu, 28 Nov 2024 16:35:51 -0800 Subject: Move FdTable to public location, fix up imports --- src/tools/miri/src/shims/files.rs | 455 +++++++++++++++++++++ src/tools/miri/src/shims/mod.rs | 4 +- src/tools/miri/src/shims/unix/fd.rs | 447 +------------------- src/tools/miri/src/shims/unix/fs.rs | 4 +- src/tools/miri/src/shims/unix/linux_like/epoll.rs | 3 +- .../miri/src/shims/unix/linux_like/eventfd.rs | 3 +- src/tools/miri/src/shims/unix/mod.rs | 2 +- src/tools/miri/src/shims/unix/unnamed_socket.rs | 5 +- 8 files changed, 467 insertions(+), 456 deletions(-) create mode 100644 src/tools/miri/src/shims/files.rs (limited to 'src/tools') diff --git a/src/tools/miri/src/shims/files.rs b/src/tools/miri/src/shims/files.rs new file mode 100644 index 00000000000..197ed726a1b --- /dev/null +++ b/src/tools/miri/src/shims/files.rs @@ -0,0 +1,455 @@ +use std::any::Any; +use std::collections::BTreeMap; +use std::io; +use std::io::{IsTerminal, Read, SeekFrom, Write}; +use std::ops::Deref; +use std::rc::{Rc, Weak}; + +use rustc_abi::Size; + +use crate::*; + +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub(crate) enum FlockOp { + SharedLock { nonblocking: bool }, + ExclusiveLock { nonblocking: bool }, + Unlock, +} + +/// Represents an open file description. +pub trait FileDescription: std::fmt::Debug + Any { + fn name(&self) -> &'static str; + + /// Reads as much as possible into the given buffer `ptr`. + /// `len` indicates how many bytes we should try to read. + /// `dest` is where the return value should be stored: number of bytes read, or `-1` in case of error. + fn read<'tcx>( + &self, + _self_ref: &FileDescriptionRef, + _communicate_allowed: bool, + _ptr: Pointer, + _len: usize, + _dest: &MPlaceTy<'tcx>, + _ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx> { + throw_unsup_format!("cannot read from {}", self.name()); + } + + /// Writes as much as possible from the given buffer `ptr`. + /// `len` indicates how many bytes we should try to write. + /// `dest` is where the return value should be stored: number of bytes written, or `-1` in case of error. + fn write<'tcx>( + &self, + _self_ref: &FileDescriptionRef, + _communicate_allowed: bool, + _ptr: Pointer, + _len: usize, + _dest: &MPlaceTy<'tcx>, + _ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx> { + throw_unsup_format!("cannot write to {}", self.name()); + } + + /// Reads as much as possible into the given buffer `ptr` from a given offset. + /// `len` indicates how many bytes we should try to read. + /// `dest` is where the return value should be stored: number of bytes read, or `-1` in case of error. + fn pread<'tcx>( + &self, + _communicate_allowed: bool, + _offset: u64, + _ptr: Pointer, + _len: usize, + _dest: &MPlaceTy<'tcx>, + _ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx> { + throw_unsup_format!("cannot pread from {}", self.name()); + } + + /// Writes as much as possible from the given buffer `ptr` starting at a given offset. + /// `ptr` is the pointer to the user supplied read buffer. + /// `len` indicates how many bytes we should try to write. + /// `dest` is where the return value should be stored: number of bytes written, or `-1` in case of error. + fn pwrite<'tcx>( + &self, + _communicate_allowed: bool, + _ptr: Pointer, + _len: usize, + _offset: u64, + _dest: &MPlaceTy<'tcx>, + _ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx> { + throw_unsup_format!("cannot pwrite to {}", self.name()); + } + + /// Seeks to the given offset (which can be relative to the beginning, end, or current position). + /// Returns the new position from the start of the stream. + fn seek<'tcx>( + &self, + _communicate_allowed: bool, + _offset: SeekFrom, + ) -> InterpResult<'tcx, io::Result> { + throw_unsup_format!("cannot seek on {}", self.name()); + } + + fn close<'tcx>( + self: Box, + _communicate_allowed: bool, + _ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx, io::Result<()>> { + throw_unsup_format!("cannot close {}", self.name()); + } + + fn flock<'tcx>( + &self, + _communicate_allowed: bool, + _op: FlockOp, + ) -> InterpResult<'tcx, io::Result<()>> { + throw_unsup_format!("cannot flock {}", self.name()); + } + + fn is_tty(&self, _communicate_allowed: bool) -> bool { + // Most FDs are not tty's and the consequence of a wrong `false` are minor, + // so we use a default impl here. + false + } + + /// Check the readiness of file description. + fn get_epoll_ready_events<'tcx>( + &self, + ) -> InterpResult<'tcx, crate::shims::unix::linux::epoll::EpollReadyEvents> { + throw_unsup_format!("{}: epoll does not support this file description", self.name()); + } +} + +impl dyn FileDescription { + #[inline(always)] + pub fn downcast(&self) -> Option<&T> { + (self as &dyn Any).downcast_ref() + } +} + +impl FileDescription for io::Stdin { + fn name(&self) -> &'static str { + "stdin" + } + + fn read<'tcx>( + &self, + _self_ref: &FileDescriptionRef, + communicate_allowed: bool, + ptr: Pointer, + len: usize, + dest: &MPlaceTy<'tcx>, + ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx> { + let mut bytes = vec![0; len]; + if !communicate_allowed { + // We want isolation mode to be deterministic, so we have to disallow all reads, even stdin. + helpers::isolation_abort_error("`read` from stdin")?; + } + let result = Read::read(&mut { self }, &mut bytes); + match result { + Ok(read_size) => ecx.return_read_success(ptr, &bytes, read_size, dest), + Err(e) => ecx.set_last_error_and_return(e, dest), + } + } + + fn is_tty(&self, communicate_allowed: bool) -> bool { + communicate_allowed && self.is_terminal() + } +} + +impl FileDescription for io::Stdout { + fn name(&self) -> &'static str { + "stdout" + } + + fn write<'tcx>( + &self, + _self_ref: &FileDescriptionRef, + _communicate_allowed: bool, + ptr: Pointer, + len: usize, + dest: &MPlaceTy<'tcx>, + ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx> { + let bytes = ecx.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(len))?; + // We allow writing to stderr even with isolation enabled. + let result = Write::write(&mut { self }, bytes); + // Stdout is buffered, flush to make sure it appears on the + // screen. This is the write() syscall of the interpreted + // program, we want it to correspond to a write() syscall on + // the host -- there is no good in adding extra buffering + // here. + io::stdout().flush().unwrap(); + match result { + Ok(write_size) => ecx.return_write_success(write_size, dest), + Err(e) => ecx.set_last_error_and_return(e, dest), + } + } + + fn is_tty(&self, communicate_allowed: bool) -> bool { + communicate_allowed && self.is_terminal() + } +} + +impl FileDescription for io::Stderr { + fn name(&self) -> &'static str { + "stderr" + } + + fn write<'tcx>( + &self, + _self_ref: &FileDescriptionRef, + _communicate_allowed: bool, + ptr: Pointer, + len: usize, + dest: &MPlaceTy<'tcx>, + ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx> { + let bytes = ecx.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(len))?; + // We allow writing to stderr even with isolation enabled. + // No need to flush, stderr is not buffered. + let result = Write::write(&mut { self }, bytes); + match result { + Ok(write_size) => ecx.return_write_success(write_size, dest), + Err(e) => ecx.set_last_error_and_return(e, dest), + } + } + + fn is_tty(&self, communicate_allowed: bool) -> bool { + communicate_allowed && self.is_terminal() + } +} + +/// Like /dev/null +#[derive(Debug)] +pub struct NullOutput; + +impl FileDescription for NullOutput { + fn name(&self) -> &'static str { + "stderr and stdout" + } + + fn write<'tcx>( + &self, + _self_ref: &FileDescriptionRef, + _communicate_allowed: bool, + _ptr: Pointer, + len: usize, + dest: &MPlaceTy<'tcx>, + ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx> { + // We just don't write anything, but report to the user that we did. + ecx.return_write_success(len, dest) + } +} + +/// Structure contains both the file description and its unique identifier. +#[derive(Clone, Debug)] +pub struct FileDescWithId { + id: FdId, + file_description: Box, +} + +#[derive(Clone, Debug)] +pub struct FileDescriptionRef(Rc>); + +impl Deref for FileDescriptionRef { + type Target = dyn FileDescription; + + fn deref(&self) -> &Self::Target { + &*self.0.file_description + } +} + +impl FileDescriptionRef { + fn new(fd: impl FileDescription, id: FdId) -> Self { + FileDescriptionRef(Rc::new(FileDescWithId { id, file_description: Box::new(fd) })) + } + + pub fn close<'tcx>( + self, + communicate_allowed: bool, + ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx, io::Result<()>> { + // Destroy this `Rc` using `into_inner` so we can call `close` instead of + // implicitly running the destructor of the file description. + let id = self.get_id(); + match Rc::into_inner(self.0) { + Some(fd) => { + // Remove entry from the global epoll_event_interest table. + ecx.machine.epoll_interests.remove(id); + + fd.file_description.close(communicate_allowed, ecx) + } + None => interp_ok(Ok(())), + } + } + + pub fn downgrade(&self) -> WeakFileDescriptionRef { + WeakFileDescriptionRef { weak_ref: Rc::downgrade(&self.0) } + } + + pub fn get_id(&self) -> FdId { + self.0.id + } +} + +/// Holds a weak reference to the actual file description. +#[derive(Clone, Debug, Default)] +pub struct WeakFileDescriptionRef { + weak_ref: Weak>, +} + +impl WeakFileDescriptionRef { + pub fn upgrade(&self) -> Option { + if let Some(file_desc_with_id) = self.weak_ref.upgrade() { + return Some(FileDescriptionRef(file_desc_with_id)); + } + None + } +} + +impl VisitProvenance for WeakFileDescriptionRef { + fn visit_provenance(&self, _visit: &mut VisitWith<'_>) { + // A weak reference can never be the only reference to some pointer or place. + // Since the actual file description is tracked by strong ref somewhere, + // it is ok to make this a NOP operation. + } +} + +/// A unique id for file descriptions. While we could use the address, considering that +/// is definitely unique, the address would expose interpreter internal state when used +/// for sorting things. So instead we generate a unique id per file description that stays +/// the same even if a file descriptor is duplicated and gets a new integer file descriptor. +#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Ord, PartialOrd)] +pub struct FdId(usize); + +/// The file descriptor table +#[derive(Debug)] +pub struct FdTable { + pub fds: BTreeMap, + /// Unique identifier for file description, used to differentiate between various file description. + next_file_description_id: FdId, +} + +impl VisitProvenance for FdTable { + fn visit_provenance(&self, _visit: &mut VisitWith<'_>) { + // All our FileDescription instances do not have any tags. + } +} + +impl FdTable { + fn new() -> Self { + FdTable { fds: BTreeMap::new(), next_file_description_id: FdId(0) } + } + pub(crate) fn init(mute_stdout_stderr: bool) -> FdTable { + let mut fds = FdTable::new(); + fds.insert_new(io::stdin()); + if mute_stdout_stderr { + assert_eq!(fds.insert_new(NullOutput), 1); + assert_eq!(fds.insert_new(NullOutput), 2); + } else { + assert_eq!(fds.insert_new(io::stdout()), 1); + assert_eq!(fds.insert_new(io::stderr()), 2); + } + fds + } + + pub fn new_ref(&mut self, fd: impl FileDescription) -> FileDescriptionRef { + let file_handle = FileDescriptionRef::new(fd, self.next_file_description_id); + self.next_file_description_id = FdId(self.next_file_description_id.0.strict_add(1)); + file_handle + } + + /// Insert a new file description to the FdTable. + pub fn insert_new(&mut self, fd: impl FileDescription) -> i32 { + let fd_ref = self.new_ref(fd); + self.insert(fd_ref) + } + + pub fn insert(&mut self, fd_ref: FileDescriptionRef) -> i32 { + self.insert_with_min_num(fd_ref, 0) + } + + /// Insert a file description, giving it a file descriptor that is at least `min_fd_num`. + pub fn insert_with_min_num(&mut self, file_handle: FileDescriptionRef, min_fd_num: i32) -> i32 { + // Find the lowest unused FD, starting from min_fd. If the first such unused FD is in + // between used FDs, the find_map combinator will return it. If the first such unused FD + // is after all other used FDs, the find_map combinator will return None, and we will use + // the FD following the greatest FD thus far. + let candidate_new_fd = + self.fds.range(min_fd_num..).zip(min_fd_num..).find_map(|((fd_num, _fd), counter)| { + if *fd_num != counter { + // There was a gap in the fds stored, return the first unused one + // (note that this relies on BTreeMap iterating in key order) + Some(counter) + } else { + // This fd is used, keep going + None + } + }); + let new_fd_num = candidate_new_fd.unwrap_or_else(|| { + // find_map ran out of BTreeMap entries before finding a free fd, use one plus the + // maximum fd in the map + self.fds.last_key_value().map(|(fd_num, _)| fd_num.strict_add(1)).unwrap_or(min_fd_num) + }); + + self.fds.try_insert(new_fd_num, file_handle).unwrap(); + new_fd_num + } + + pub fn get(&self, fd_num: i32) -> Option { + let fd = self.fds.get(&fd_num)?; + Some(fd.clone()) + } + + pub fn remove(&mut self, fd_num: i32) -> Option { + self.fds.remove(&fd_num) + } + + pub fn is_fd_num(&self, fd_num: i32) -> bool { + self.fds.contains_key(&fd_num) + } +} + +impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} +pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { + /// Helper to implement `FileDescription::read`: + /// This is only used when `read` is successful. + /// `actual_read_size` should be the return value of some underlying `read` call that used + /// `bytes` as its output buffer. + /// The length of `bytes` must not exceed either the host's or the target's `isize`. + /// `bytes` is written to `buf` and the size is written to `dest`. + fn return_read_success( + &mut self, + buf: Pointer, + bytes: &[u8], + actual_read_size: usize, + dest: &MPlaceTy<'tcx>, + ) -> InterpResult<'tcx> { + let this = self.eval_context_mut(); + // If reading to `bytes` did not fail, we write those bytes to the buffer. + // Crucially, if fewer than `bytes.len()` bytes were read, only write + // that much into the output buffer! + this.write_bytes_ptr(buf, bytes[..actual_read_size].iter().copied())?; + + // The actual read size is always less than what got originally requested so this cannot fail. + this.write_int(u64::try_from(actual_read_size).unwrap(), dest)?; + interp_ok(()) + } + + /// Helper to implement `FileDescription::write`: + /// This function is only used when `write` is successful, and writes `actual_write_size` to `dest` + fn return_write_success( + &mut self, + actual_write_size: usize, + dest: &MPlaceTy<'tcx>, + ) -> InterpResult<'tcx> { + let this = self.eval_context_mut(); + // The actual write size is always less than what got originally requested so this cannot fail. + this.write_int(u64::try_from(actual_write_size).unwrap(), dest)?; + interp_ok(()) + } +} diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs index b9317ac1a15..61681edcf76 100644 --- a/src/tools/miri/src/shims/mod.rs +++ b/src/tools/miri/src/shims/mod.rs @@ -2,6 +2,7 @@ mod alloc; mod backtrace; +mod files; #[cfg(unix)] mod native_lib; mod unix; @@ -18,7 +19,8 @@ pub mod panic; pub mod time; pub mod tls; -pub use self::unix::{DirTable, EpollInterestTable, FdTable}; +pub use self::files::FdTable; +pub use self::unix::{DirTable, EpollInterestTable}; /// What needs to be done after emulating an item (a shim or an intrinsic) is done. pub enum EmulateItemResult { diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs index 4e80630e674..a9a24dd2958 100644 --- a/src/tools/miri/src/shims/unix/fd.rs +++ b/src/tools/miri/src/shims/unix/fd.rs @@ -1,422 +1,16 @@ //! General management of file descriptors, and support for //! standard file descriptors (stdin/stdout/stderr). -use std::any::Any; -use std::collections::BTreeMap; -use std::io::{self, ErrorKind, IsTerminal, Read, SeekFrom, Write}; -use std::ops::Deref; -use std::rc::{Rc, Weak}; +use std::io::ErrorKind; use rustc_abi::Size; use crate::helpers::check_min_arg_count; +use crate::shims::files::FlockOp; use crate::shims::unix::linux_like::epoll::EpollReadyEvents; use crate::shims::unix::*; use crate::*; -#[derive(Debug, Clone, Copy, Eq, PartialEq)] -pub(crate) enum FlockOp { - SharedLock { nonblocking: bool }, - ExclusiveLock { nonblocking: bool }, - Unlock, -} - -/// Represents an open file description. -pub trait FileDescription: std::fmt::Debug + Any { - fn name(&self) -> &'static str; - - /// Reads as much as possible into the given buffer `ptr`. - /// `len` indicates how many bytes we should try to read. - /// `dest` is where the return value should be stored: number of bytes read, or `-1` in case of error. - fn read<'tcx>( - &self, - _self_ref: &FileDescriptionRef, - _communicate_allowed: bool, - _ptr: Pointer, - _len: usize, - _dest: &MPlaceTy<'tcx>, - _ecx: &mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx> { - throw_unsup_format!("cannot read from {}", self.name()); - } - - /// Writes as much as possible from the given buffer `ptr`. - /// `len` indicates how many bytes we should try to write. - /// `dest` is where the return value should be stored: number of bytes written, or `-1` in case of error. - fn write<'tcx>( - &self, - _self_ref: &FileDescriptionRef, - _communicate_allowed: bool, - _ptr: Pointer, - _len: usize, - _dest: &MPlaceTy<'tcx>, - _ecx: &mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx> { - throw_unsup_format!("cannot write to {}", self.name()); - } - - /// Reads as much as possible into the given buffer `ptr` from a given offset. - /// `len` indicates how many bytes we should try to read. - /// `dest` is where the return value should be stored: number of bytes read, or `-1` in case of error. - fn pread<'tcx>( - &self, - _communicate_allowed: bool, - _offset: u64, - _ptr: Pointer, - _len: usize, - _dest: &MPlaceTy<'tcx>, - _ecx: &mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx> { - throw_unsup_format!("cannot pread from {}", self.name()); - } - - /// Writes as much as possible from the given buffer `ptr` starting at a given offset. - /// `ptr` is the pointer to the user supplied read buffer. - /// `len` indicates how many bytes we should try to write. - /// `dest` is where the return value should be stored: number of bytes written, or `-1` in case of error. - fn pwrite<'tcx>( - &self, - _communicate_allowed: bool, - _ptr: Pointer, - _len: usize, - _offset: u64, - _dest: &MPlaceTy<'tcx>, - _ecx: &mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx> { - throw_unsup_format!("cannot pwrite to {}", self.name()); - } - - /// Seeks to the given offset (which can be relative to the beginning, end, or current position). - /// Returns the new position from the start of the stream. - fn seek<'tcx>( - &self, - _communicate_allowed: bool, - _offset: SeekFrom, - ) -> InterpResult<'tcx, io::Result> { - throw_unsup_format!("cannot seek on {}", self.name()); - } - - fn close<'tcx>( - self: Box, - _communicate_allowed: bool, - _ecx: &mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx, io::Result<()>> { - throw_unsup_format!("cannot close {}", self.name()); - } - - fn flock<'tcx>( - &self, - _communicate_allowed: bool, - _op: FlockOp, - ) -> InterpResult<'tcx, io::Result<()>> { - throw_unsup_format!("cannot flock {}", self.name()); - } - - fn is_tty(&self, _communicate_allowed: bool) -> bool { - // Most FDs are not tty's and the consequence of a wrong `false` are minor, - // so we use a default impl here. - false - } - - /// Check the readiness of file description. - fn get_epoll_ready_events<'tcx>(&self) -> InterpResult<'tcx, EpollReadyEvents> { - throw_unsup_format!("{}: epoll does not support this file description", self.name()); - } -} - -impl dyn FileDescription { - #[inline(always)] - pub fn downcast(&self) -> Option<&T> { - (self as &dyn Any).downcast_ref() - } -} - -impl FileDescription for io::Stdin { - fn name(&self) -> &'static str { - "stdin" - } - - fn read<'tcx>( - &self, - _self_ref: &FileDescriptionRef, - communicate_allowed: bool, - ptr: Pointer, - len: usize, - dest: &MPlaceTy<'tcx>, - ecx: &mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx> { - let mut bytes = vec![0; len]; - if !communicate_allowed { - // We want isolation mode to be deterministic, so we have to disallow all reads, even stdin. - helpers::isolation_abort_error("`read` from stdin")?; - } - let result = Read::read(&mut { self }, &mut bytes); - match result { - Ok(read_size) => ecx.return_read_success(ptr, &bytes, read_size, dest), - Err(e) => ecx.set_last_error_and_return(e, dest), - } - } - - fn is_tty(&self, communicate_allowed: bool) -> bool { - communicate_allowed && self.is_terminal() - } -} - -impl FileDescription for io::Stdout { - fn name(&self) -> &'static str { - "stdout" - } - - fn write<'tcx>( - &self, - _self_ref: &FileDescriptionRef, - _communicate_allowed: bool, - ptr: Pointer, - len: usize, - dest: &MPlaceTy<'tcx>, - ecx: &mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx> { - let bytes = ecx.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(len))?; - // We allow writing to stderr even with isolation enabled. - let result = Write::write(&mut { self }, bytes); - // Stdout is buffered, flush to make sure it appears on the - // screen. This is the write() syscall of the interpreted - // program, we want it to correspond to a write() syscall on - // the host -- there is no good in adding extra buffering - // here. - io::stdout().flush().unwrap(); - match result { - Ok(write_size) => ecx.return_write_success(write_size, dest), - Err(e) => ecx.set_last_error_and_return(e, dest), - } - } - - fn is_tty(&self, communicate_allowed: bool) -> bool { - communicate_allowed && self.is_terminal() - } -} - -impl FileDescription for io::Stderr { - fn name(&self) -> &'static str { - "stderr" - } - - fn write<'tcx>( - &self, - _self_ref: &FileDescriptionRef, - _communicate_allowed: bool, - ptr: Pointer, - len: usize, - dest: &MPlaceTy<'tcx>, - ecx: &mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx> { - let bytes = ecx.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(len))?; - // We allow writing to stderr even with isolation enabled. - // No need to flush, stderr is not buffered. - let result = Write::write(&mut { self }, bytes); - match result { - Ok(write_size) => ecx.return_write_success(write_size, dest), - Err(e) => ecx.set_last_error_and_return(e, dest), - } - } - - fn is_tty(&self, communicate_allowed: bool) -> bool { - communicate_allowed && self.is_terminal() - } -} - -/// Like /dev/null -#[derive(Debug)] -pub struct NullOutput; - -impl FileDescription for NullOutput { - fn name(&self) -> &'static str { - "stderr and stdout" - } - - fn write<'tcx>( - &self, - _self_ref: &FileDescriptionRef, - _communicate_allowed: bool, - _ptr: Pointer, - len: usize, - dest: &MPlaceTy<'tcx>, - ecx: &mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx> { - // We just don't write anything, but report to the user that we did. - ecx.return_write_success(len, dest) - } -} - -/// Structure contains both the file description and its unique identifier. -#[derive(Clone, Debug)] -pub struct FileDescWithId { - id: FdId, - file_description: Box, -} - -#[derive(Clone, Debug)] -pub struct FileDescriptionRef(Rc>); - -impl Deref for FileDescriptionRef { - type Target = dyn FileDescription; - - fn deref(&self) -> &Self::Target { - &*self.0.file_description - } -} - -impl FileDescriptionRef { - fn new(fd: impl FileDescription, id: FdId) -> Self { - FileDescriptionRef(Rc::new(FileDescWithId { id, file_description: Box::new(fd) })) - } - - pub fn close<'tcx>( - self, - communicate_allowed: bool, - ecx: &mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx, io::Result<()>> { - // Destroy this `Rc` using `into_inner` so we can call `close` instead of - // implicitly running the destructor of the file description. - let id = self.get_id(); - match Rc::into_inner(self.0) { - Some(fd) => { - // Remove entry from the global epoll_event_interest table. - ecx.machine.epoll_interests.remove(id); - - fd.file_description.close(communicate_allowed, ecx) - } - None => interp_ok(Ok(())), - } - } - - pub fn downgrade(&self) -> WeakFileDescriptionRef { - WeakFileDescriptionRef { weak_ref: Rc::downgrade(&self.0) } - } - - pub fn get_id(&self) -> FdId { - self.0.id - } -} - -/// Holds a weak reference to the actual file description. -#[derive(Clone, Debug, Default)] -pub struct WeakFileDescriptionRef { - weak_ref: Weak>, -} - -impl WeakFileDescriptionRef { - pub fn upgrade(&self) -> Option { - if let Some(file_desc_with_id) = self.weak_ref.upgrade() { - return Some(FileDescriptionRef(file_desc_with_id)); - } - None - } -} - -impl VisitProvenance for WeakFileDescriptionRef { - fn visit_provenance(&self, _visit: &mut VisitWith<'_>) { - // A weak reference can never be the only reference to some pointer or place. - // Since the actual file description is tracked by strong ref somewhere, - // it is ok to make this a NOP operation. - } -} - -/// A unique id for file descriptions. While we could use the address, considering that -/// is definitely unique, the address would expose interpreter internal state when used -/// for sorting things. So instead we generate a unique id per file description that stays -/// the same even if a file descriptor is duplicated and gets a new integer file descriptor. -#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Ord, PartialOrd)] -pub struct FdId(usize); - -/// The file descriptor table -#[derive(Debug)] -pub struct FdTable { - pub fds: BTreeMap, - /// Unique identifier for file description, used to differentiate between various file description. - next_file_description_id: FdId, -} - -impl VisitProvenance for FdTable { - fn visit_provenance(&self, _visit: &mut VisitWith<'_>) { - // All our FileDescription instances do not have any tags. - } -} - -impl FdTable { - fn new() -> Self { - FdTable { fds: BTreeMap::new(), next_file_description_id: FdId(0) } - } - pub(crate) fn init(mute_stdout_stderr: bool) -> FdTable { - let mut fds = FdTable::new(); - fds.insert_new(io::stdin()); - if mute_stdout_stderr { - assert_eq!(fds.insert_new(NullOutput), 1); - assert_eq!(fds.insert_new(NullOutput), 2); - } else { - assert_eq!(fds.insert_new(io::stdout()), 1); - assert_eq!(fds.insert_new(io::stderr()), 2); - } - fds - } - - pub fn new_ref(&mut self, fd: impl FileDescription) -> FileDescriptionRef { - let file_handle = FileDescriptionRef::new(fd, self.next_file_description_id); - self.next_file_description_id = FdId(self.next_file_description_id.0.strict_add(1)); - file_handle - } - - /// Insert a new file description to the FdTable. - pub fn insert_new(&mut self, fd: impl FileDescription) -> i32 { - let fd_ref = self.new_ref(fd); - self.insert(fd_ref) - } - - pub fn insert(&mut self, fd_ref: FileDescriptionRef) -> i32 { - self.insert_with_min_num(fd_ref, 0) - } - - /// Insert a file description, giving it a file descriptor that is at least `min_fd_num`. - fn insert_with_min_num(&mut self, file_handle: FileDescriptionRef, min_fd_num: i32) -> i32 { - // Find the lowest unused FD, starting from min_fd. If the first such unused FD is in - // between used FDs, the find_map combinator will return it. If the first such unused FD - // is after all other used FDs, the find_map combinator will return None, and we will use - // the FD following the greatest FD thus far. - let candidate_new_fd = - self.fds.range(min_fd_num..).zip(min_fd_num..).find_map(|((fd_num, _fd), counter)| { - if *fd_num != counter { - // There was a gap in the fds stored, return the first unused one - // (note that this relies on BTreeMap iterating in key order) - Some(counter) - } else { - // This fd is used, keep going - None - } - }); - let new_fd_num = candidate_new_fd.unwrap_or_else(|| { - // find_map ran out of BTreeMap entries before finding a free fd, use one plus the - // maximum fd in the map - self.fds.last_key_value().map(|(fd_num, _)| fd_num.strict_add(1)).unwrap_or(min_fd_num) - }); - - self.fds.try_insert(new_fd_num, file_handle).unwrap(); - new_fd_num - } - - pub fn get(&self, fd_num: i32) -> Option { - let fd = self.fds.get(&fd_num)?; - Some(fd.clone()) - } - - pub fn remove(&mut self, fd_num: i32) -> Option { - self.fds.remove(&fd_num) - } - - pub fn is_fd_num(&self, fd_num: i32) -> bool { - self.fds.contains_key(&fd_num) - } -} - impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn dup(&mut self, old_fd_num: i32) -> InterpResult<'tcx, Scalar> { @@ -647,41 +241,4 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { }; interp_ok(()) } - - /// Helper to implement `FileDescription::read`: - /// This is only used when `read` is successful. - /// `actual_read_size` should be the return value of some underlying `read` call that used - /// `bytes` as its output buffer. - /// The length of `bytes` must not exceed either the host's or the target's `isize`. - /// `bytes` is written to `buf` and the size is written to `dest`. - fn return_read_success( - &mut self, - buf: Pointer, - bytes: &[u8], - actual_read_size: usize, - dest: &MPlaceTy<'tcx>, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - // If reading to `bytes` did not fail, we write those bytes to the buffer. - // Crucially, if fewer than `bytes.len()` bytes were read, only write - // that much into the output buffer! - this.write_bytes_ptr(buf, bytes[..actual_read_size].iter().copied())?; - - // The actual read size is always less than what got originally requested so this cannot fail. - this.write_int(u64::try_from(actual_read_size).unwrap(), dest)?; - interp_ok(()) - } - - /// Helper to implement `FileDescription::write`: - /// This function is only used when `write` is successful, and writes `actual_write_size` to `dest` - fn return_write_success( - &mut self, - actual_write_size: usize, - dest: &MPlaceTy<'tcx>, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - // The actual write size is always less than what got originally requested so this cannot fail. - this.write_int(u64::try_from(actual_write_size).unwrap(), dest)?; - interp_ok(()) - } } diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 070fdc94695..f363627da93 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -11,12 +11,10 @@ use std::time::SystemTime; use rustc_abi::Size; use rustc_data_structures::fx::FxHashMap; -use self::fd::FlockOp; use self::shims::time::system_time_to_duration; use crate::helpers::check_min_arg_count; +use crate::shims::files::{EvalContextExt as _, FileDescription, FileDescriptionRef, FlockOp}; use crate::shims::os_str::bytes_to_os_str; -use crate::shims::unix::fd::FileDescriptionRef; -use crate::shims::unix::*; use crate::*; #[derive(Debug)] diff --git a/src/tools/miri/src/shims/unix/linux_like/epoll.rs b/src/tools/miri/src/shims/unix/linux_like/epoll.rs index b20b12528db..d0317132c6c 100644 --- a/src/tools/miri/src/shims/unix/linux_like/epoll.rs +++ b/src/tools/miri/src/shims/unix/linux_like/epoll.rs @@ -5,8 +5,7 @@ use std::rc::{Rc, Weak}; use std::time::Duration; use crate::concurrency::VClock; -use crate::shims::unix::fd::{FdId, FileDescriptionRef, WeakFileDescriptionRef}; -use crate::shims::unix::*; +use crate::shims::files::{FdId, FileDescription, FileDescriptionRef, WeakFileDescriptionRef}; use crate::*; /// An `Epoll` file descriptor connects file handles and epoll events diff --git a/src/tools/miri/src/shims/unix/linux_like/eventfd.rs b/src/tools/miri/src/shims/unix/linux_like/eventfd.rs index 61c91877946..5b51b5a0f09 100644 --- a/src/tools/miri/src/shims/unix/linux_like/eventfd.rs +++ b/src/tools/miri/src/shims/unix/linux_like/eventfd.rs @@ -4,9 +4,8 @@ use std::io; use std::io::ErrorKind; use crate::concurrency::VClock; -use crate::shims::unix::fd::{FileDescriptionRef, WeakFileDescriptionRef}; +use crate::shims::files::{FileDescription, FileDescriptionRef, WeakFileDescriptionRef}; use crate::shims::unix::linux_like::epoll::{EpollReadyEvents, EvalContextExt as _}; -use crate::shims::unix::*; use crate::*; /// Maximum value that the eventfd counter can hold. diff --git a/src/tools/miri/src/shims/unix/mod.rs b/src/tools/miri/src/shims/unix/mod.rs index 0620b57753a..fea5bc959c6 100644 --- a/src/tools/miri/src/shims/unix/mod.rs +++ b/src/tools/miri/src/shims/unix/mod.rs @@ -17,7 +17,7 @@ mod solarish; // All the Unix-specific extension traits pub use self::env::{EvalContextExt as _, UnixEnvVars}; -pub use self::fd::{EvalContextExt as _, FdTable, FileDescription}; +pub use self::fd::EvalContextExt as _; pub use self::fs::{DirTable, EvalContextExt as _}; pub use self::linux_like::epoll::EpollInterestTable; pub use self::mem::EvalContextExt as _; diff --git a/src/tools/miri/src/shims/unix/unnamed_socket.rs b/src/tools/miri/src/shims/unix/unnamed_socket.rs index 232f4500dba..5d2b767fe8b 100644 --- a/src/tools/miri/src/shims/unix/unnamed_socket.rs +++ b/src/tools/miri/src/shims/unix/unnamed_socket.rs @@ -10,9 +10,10 @@ use std::io::{ErrorKind, Read}; use rustc_abi::Size; use crate::concurrency::VClock; -use crate::shims::unix::fd::{FileDescriptionRef, WeakFileDescriptionRef}; +use crate::shims::files::{ + EvalContextExt as _, FileDescription, FileDescriptionRef, WeakFileDescriptionRef, +}; use crate::shims::unix::linux_like::epoll::{EpollReadyEvents, EvalContextExt as _}; -use crate::shims::unix::*; use crate::*; /// The maximum capacity of the socketpair buffer in bytes. -- cgit 1.4.1-3-g733a5 From 868668e05dca0a6516f37e6fa2bfab3526f02868 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 25 Nov 2024 15:06:43 +0000 Subject: Run `cargo update` and update licenses --- Cargo.lock | 580 ++++++++++++++++++++-------------- compiler/rustc_codegen_ssa/Cargo.toml | 2 +- library/Cargo.lock | 12 +- src/tools/run-make-support/Cargo.toml | 2 +- src/tools/rustbook/Cargo.lock | 443 ++++++++++++++++++++------ src/tools/tidy/src/deps.rs | 4 +- 6 files changed, 686 insertions(+), 357 deletions(-) (limited to 'src/tools') diff --git a/Cargo.lock b/Cargo.lock index 8ccf05cc5b8..89e7d70d839 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -57,9 +57,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.18" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" [[package]] name = "ammonia" @@ -182,9 +182,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" dependencies = [ "backtrace", ] @@ -255,12 +255,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.6.0" @@ -269,9 +263,9 @@ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "blake3" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7" +checksum = "b8ee0c1824c4dea5b5f81736aff91bae041d2c07ee1192bec91054e10e3e601e" dependencies = [ "arrayref", "arrayvec", @@ -291,12 +285,12 @@ dependencies = [ [[package]] name = "bstr" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" +checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22" dependencies = [ "memchr", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "serde", ] @@ -356,9 +350,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "camino" @@ -384,9 +378,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" dependencies = [ "serde", ] @@ -411,9 +405,9 @@ version = "0.1.0" [[package]] name = "cc" -version = "1.2.0" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8" +checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" dependencies = [ "shlex", ] @@ -476,9 +470,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" dependencies = [ "clap_builder", "clap_derive", @@ -496,9 +490,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" dependencies = [ "anstream", "anstyle", @@ -509,9 +503,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.36" +version = "4.5.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86bc73de94bc81e52f3bebec71bc4463e9748f7a59166663e32044669577b0e2" +checksum = "d9647a559c112175f17cf724dc72d3645680a883c58481332779192b0d8e7a01" dependencies = [ "clap", ] @@ -525,14 +519,14 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" [[package]] name = "clippy" @@ -556,7 +550,7 @@ dependencies = [ "rustc_tools_util", "serde", "serde_json", - "syn 2.0.87", + "syn 2.0.90", "tempfile", "termize", "tokio", @@ -650,23 +644,23 @@ dependencies = [ [[package]] name = "color-print" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee543c60ff3888934877a5671f45494dd27ed4ba25c6670b9a7576b7ed7a8c0" +checksum = "3aa954171903797d5623e047d9ab69d91b493657917bdfb8c2c80ecaf9cdb6f4" dependencies = [ "color-print-proc-macro", ] [[package]] name = "color-print-proc-macro" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ff1a80c5f3cb1ca7c06ffdd71b6a6dd6d8f896c42141fbd43f50ed28dcdb93" +checksum = "692186b5ebe54007e45a59aea47ece9eb4108e141326c304cdc91699a7118a22" dependencies = [ "nom", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -770,9 +764,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -857,9 +851,9 @@ dependencies = [ [[package]] name = "curl-sys" -version = "0.4.77+curl-8.10.1" +version = "0.4.78+curl-8.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f469e8a5991f277a208224f6c7ad72ecb5f986e36d09ae1f2c1bb9259478a480" +checksum = "8eec768341c5c7789611ae51cf6c459099f22e64a5d5d0ce4892434e33821eaf" dependencies = [ "cc", "libc", @@ -891,7 +885,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -902,7 +896,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -939,7 +933,7 @@ checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -960,7 +954,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -970,7 +964,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -982,7 +976,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1060,7 +1054,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1142,12 +1136,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1185,9 +1179,9 @@ checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] name = "fastrand" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "field-offset" @@ -1213,9 +1207,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.34" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", "miniz_oxide 0.8.0", @@ -1357,7 +1351,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1482,7 +1476,7 @@ dependencies = [ "aho-corasick", "bstr", "log", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "regex-syntax 0.8.5", ] @@ -1497,11 +1491,12 @@ dependencies = [ [[package]] name = "handlebars" -version = "5.1.2" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d08485b96a0e6393e9e4d1b8d48cf74ad6c063cd905eb33f42c1ce3f0377539b" +checksum = "fd4ccde012831f9a071a637b0d4e31df31c0f6c525784b35ae76a9ac6bc1e315" dependencies = [ "log", + "num-order", "pest", "pest_derive", "serde", @@ -1522,9 +1517,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "foldhash", ] @@ -1590,7 +1585,7 @@ dependencies = [ "markup5ever", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1631,6 +1626,18 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + [[package]] name = "icu_list" version = "1.5.0" @@ -1684,6 +1691,51 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + [[package]] name = "icu_provider" version = "1.5.0" @@ -1722,7 +1774,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1739,12 +1791,23 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] @@ -1763,7 +1826,7 @@ dependencies = [ "globset", "log", "memchr", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "same-file", "walkdir", "winapi-util", @@ -1777,27 +1840,27 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown 0.15.2", "rustc-rayon", "serde", ] [[package]] name = "indicatif" -version = "0.17.8" +version = "0.17.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" +checksum = "cbf675b85ed934d3c67b5c5469701eec7db22689d0a2139d856e0925fa28b281" dependencies = [ "console", - "instant", "number_prefix", "portable-atomic", - "unicode-width 0.1.14", + "unicode-width 0.2.0", + "web-time", ] [[package]] @@ -1828,15 +1891,6 @@ dependencies = [ "xz2", ] -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] - [[package]] name = "intl-memoizer" version = "0.5.2" @@ -1873,9 +1927,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jemalloc-sys" @@ -1898,10 +1952,11 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "a865e038f7f6ed956f788f0d7d60c541fff74c7bd74272c5d4cf15c63743e705" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -1924,7 +1979,7 @@ dependencies = [ "anyhow", "clap", "fs-err", - "rustc-hash 2.0.0", + "rustc-hash 2.1.0", "rustdoc-json-types", "serde", "serde_json", @@ -1967,9 +2022,9 @@ checksum = "baff4b617f7df3d896f97fe922b64817f6cd9a756bb81d40f8883f2f66dcb401" [[package]] name = "libc" -version = "0.2.164" +version = "0.2.167" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" [[package]] name = "libdbus-sys" @@ -2002,9 +2057,9 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", "windows-targets 0.52.6", @@ -2022,7 +2077,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.6.0", + "bitflags", "libc", "redox_syscall", ] @@ -2064,9 +2119,9 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "litemap" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "lld-wrapper" @@ -2157,9 +2212,9 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.4.40" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45a38e19bd200220ef07c892b0157ad3d2365e5b5a267ca01ad12182491eea5" +checksum = "fe1f98b8d66e537d2f0ba06e7dec4f44001deec539a2d18bfc102d6a86189148" dependencies = [ "ammonia", "anyhow", @@ -2317,7 +2372,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.6.0", + "bitflags", "cfg-if", "cfg_aliases", "libc", @@ -2420,6 +2475,21 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-modular" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17bb261bf36fa7d83f4c294f834e91256769097b3cb505d44831e0a179ac647f" + +[[package]] +name = "num-order" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537b596b97c40fcf8056d153049eb22f481c17ebce72a513ec9286e4986d1bb6" +dependencies = [ + "num-modular", +] + [[package]] name = "num-rational" version = "0.4.2" @@ -2473,7 +2543,7 @@ checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "crc32fast", "flate2", - "hashbrown 0.15.0", + "hashbrown 0.15.2", "indexmap", "memchr", "ruzstd", @@ -2621,9 +2691,9 @@ dependencies = [ [[package]] name = "pathdiff" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" [[package]] name = "percent-encoding" @@ -2671,7 +2741,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -2773,9 +2843,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" [[package]] name = "powerfmt" @@ -2816,18 +2886,18 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] [[package]] name = "psm" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa37f80ca58604976033fae9515a8a2989fc13797d953f7c04fb8fa36a11f205" +checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810" dependencies = [ "cc", ] @@ -2838,7 +2908,7 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags 2.6.0", + "bitflags", "memchr", "unicase", ] @@ -2849,7 +2919,7 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993" dependencies = [ - "bitflags 2.6.0", + "bitflags", "memchr", "pulldown-cmark-escape 0.10.1", "unicase", @@ -2861,7 +2931,7 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625" dependencies = [ - "bitflags 2.6.0", + "bitflags", "memchr", "pulldown-cmark-escape 0.11.0", "unicase", @@ -2965,7 +3035,7 @@ version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ - "bitflags 2.6.0", + "bitflags", ] [[package]] @@ -2987,7 +3057,7 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "regex-syntax 0.8.5", ] @@ -3011,9 +3081,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -3079,9 +3149,9 @@ dependencies = [ "proc-macro2", "quote", "rinja_parser", - "rustc-hash 2.0.0", + "rustc-hash 2.1.0", "serde", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -3114,7 +3184,7 @@ dependencies = [ "regex", "serde_json", "similar", - "wasmparser 0.216.0", + "wasmparser 0.219.1", ] [[package]] @@ -3143,9 +3213,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" +checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" [[package]] name = "rustc-main" @@ -3210,7 +3280,7 @@ version = "1.0.1" name = "rustc_abi" version = "0.0.0" dependencies = [ - "bitflags 2.6.0", + "bitflags", "rand", "rand_xoshiro", "rustc_data_structures", @@ -3224,11 +3294,11 @@ dependencies = [ [[package]] name = "rustc_apfloat" -version = "0.2.1+llvm-462a31f5a5ab" +version = "0.2.2+llvm-462a31f5a5ab" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "886d94c63c812a8037c4faca2607453a0fa4cf82f734665266876b022244543f" +checksum = "121e2195ff969977a4e2b5c9965ea867fce7e4cb5aee5b09dee698a7932d574f" dependencies = [ - "bitflags 1.3.2", + "bitflags", "smallvec", ] @@ -3243,7 +3313,7 @@ dependencies = [ name = "rustc_ast" version = "0.0.0" dependencies = [ - "bitflags 2.6.0", + "bitflags", "memchr", "rustc_ast_ir", "rustc_data_structures", @@ -3406,7 +3476,7 @@ dependencies = [ name = "rustc_codegen_llvm" version = "0.0.0" dependencies = [ - "bitflags 2.6.0", + "bitflags", "itertools", "libc", "measureme", @@ -3444,7 +3514,7 @@ version = "0.0.0" dependencies = [ "ar_archive_writer", "arrayvec", - "bitflags 2.6.0", + "bitflags", "cc", "either", "itertools", @@ -3481,7 +3551,7 @@ dependencies = [ "thin-vec", "thorin-dwp", "tracing", - "wasm-encoder 0.216.0", + "wasm-encoder 0.219.1", "windows", ] @@ -3516,7 +3586,7 @@ name = "rustc_data_structures" version = "0.0.0" dependencies = [ "arrayvec", - "bitflags 2.6.0", + "bitflags", "either", "elsa", "ena", @@ -3527,7 +3597,7 @@ dependencies = [ "memmap2", "parking_lot", "portable-atomic", - "rustc-hash 2.0.0", + "rustc-hash 2.1.0", "rustc-rayon", "rustc-stable-hash", "rustc_arena", @@ -3700,7 +3770,7 @@ dependencies = [ "fluent-syntax", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "unic-langid", ] @@ -3834,7 +3904,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -3982,7 +4052,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "synstructure", ] @@ -3990,7 +4060,7 @@ dependencies = [ name = "rustc_metadata" version = "0.0.0" dependencies = [ - "bitflags 2.6.0", + "bitflags", "libc", "libloading", "odht", @@ -4021,7 +4091,7 @@ dependencies = [ name = "rustc_middle" version = "0.0.0" dependencies = [ - "bitflags 2.6.0", + "bitflags", "derive-where", "either", "field-offset", @@ -4172,7 +4242,7 @@ dependencies = [ name = "rustc_parse" version = "0.0.0" dependencies = [ - "bitflags 2.6.0", + "bitflags", "rustc_ast", "rustc_ast_pretty", "rustc_data_structures", @@ -4229,7 +4299,7 @@ dependencies = [ name = "rustc_pattern_analysis" version = "0.0.0" dependencies = [ - "rustc-hash 2.0.0", + "rustc-hash 2.1.0", "rustc_abi", "rustc_apfloat", "rustc_arena", @@ -4312,7 +4382,7 @@ dependencies = [ name = "rustc_resolve" version = "0.0.0" dependencies = [ - "bitflags 2.6.0", + "bitflags", "pulldown-cmark 0.11.3", "rustc_arena", "rustc_ast", @@ -4340,7 +4410,7 @@ dependencies = [ name = "rustc_sanitizers" version = "0.0.0" dependencies = [ - "bitflags 2.6.0", + "bitflags", "rustc_abi", "rustc_data_structures", "rustc_hir", @@ -4367,7 +4437,7 @@ dependencies = [ name = "rustc_session" version = "0.0.0" dependencies = [ - "bitflags 2.6.0", + "bitflags", "getopts", "libc", "rustc_abi", @@ -4448,7 +4518,7 @@ dependencies = [ name = "rustc_target" version = "0.0.0" dependencies = [ - "bitflags 2.6.0", + "bitflags", "object 0.36.5", "rustc_abi", "rustc_data_structures", @@ -4549,7 +4619,7 @@ dependencies = [ name = "rustc_type_ir" version = "0.0.0" dependencies = [ - "bitflags 2.6.0", + "bitflags", "derive-where", "indexmap", "rustc-hash 1.1.0", @@ -4571,7 +4641,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "synstructure", ] @@ -4625,7 +4695,7 @@ name = "rustdoc-json-types" version = "0.1.0" dependencies = [ "bincode", - "rustc-hash 2.0.0", + "rustc-hash 2.1.0", "serde", "serde_json", ] @@ -4660,7 +4730,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -4694,11 +4764,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.38" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ - "bitflags 2.6.0", + "bitflags", "errno", "libc", "linux-raw-sys", @@ -4737,9 +4807,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ "windows-sys 0.59.0", ] @@ -4782,29 +4852,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "indexmap", "itoa", @@ -4894,9 +4964,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -4914,9 +4984,9 @@ dependencies = [ [[package]] name = "spdx" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47317bbaf63785b53861e1ae2d11b80d6b624211d42cb20efcd210ee6f8a14bc" +checksum = "bae30cc7bfe3656d60ee99bf6836f472b0c53dddcbf335e253329abb16e535a2" dependencies = [ "smallvec", ] @@ -5055,9 +5125,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.87" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -5072,7 +5142,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -5109,9 +5179,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", "fastrand", @@ -5153,9 +5223,9 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef" +checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9" dependencies = [ "rustix", "windows-sys 0.59.0", @@ -5190,22 +5260,22 @@ checksum = "a38c90d48152c236a3ab59271da4f4ae63d678c5d7ad6b7714d7cb9760be5e4b" [[package]] name = "thiserror" -version = "1.0.66" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.66" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -5249,7 +5319,7 @@ dependencies = [ "ignore", "miropt-test-tools", "regex", - "rustc-hash 2.0.0", + "rustc-hash 2.1.0", "semver", "similar", "termcolor", @@ -5318,9 +5388,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.41.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", @@ -5390,13 +5460,13 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -5411,9 +5481,9 @@ dependencies = [ [[package]] name = "tracing-error" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" dependencies = [ "tracing", "tracing-subscriber", @@ -5567,7 +5637,7 @@ checksum = "1ed7f4237ba393424195053097c1516bd4590dc82b84f2f97c5c69e12704555b" dependencies = [ "proc-macro-hack", "quote", - "syn 2.0.87", + "syn 2.0.90", "unic-langid-impl", ] @@ -5577,17 +5647,11 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" -[[package]] -name = "unicode-bidi" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" - [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-normalization" @@ -5670,9 +5734,9 @@ dependencies = [ [[package]] name = "url" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", @@ -5685,12 +5749,24 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + [[package]] name = "utf8-width" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -5748,9 +5824,9 @@ checksum = "0f76d9fa52234153eeb40b088de91a8c13dc28a912cf6f31cd89ca4bac9024e0" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "d15e63b4482863c109d70a7b8706c1e364eb6ea449b201a76c5b89cedcec2d5c" dependencies = [ "cfg-if", "once_cell", @@ -5759,24 +5835,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "8d36ef12e3aaca16ddd3f67922bc63e48e953f126de60bd33ccc0101ef9998cd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "705440e08b42d3e4b36de7d66c944be628d579796b8090bfa3471478a2260051" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5784,22 +5860,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49" [[package]] name = "wasm-component-ld" @@ -5827,21 +5903,22 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.216.0" +version = "0.219.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04c23aebea22c8a75833ae08ed31ccc020835b12a41999e58c31464271b94a88" +checksum = "29cbbd772edcb8e7d524a82ee8cef8dd046fc14033796a754c3ad246d019fa54" dependencies = [ "leb128", + "wasmparser 0.219.1", ] [[package]] name = "wasm-encoder" -version = "0.219.1" +version = "0.221.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29cbbd772edcb8e7d524a82ee8cef8dd046fc14033796a754c3ad246d019fa54" +checksum = "de35b6c3ef1f53ac7a31b5e69bc00f1542ea337e7e7162dc34c68b537ff82690" dependencies = [ "leb128", - "wasmparser 0.219.1", + "wasmparser 0.221.0", ] [[package]] @@ -5860,23 +5937,13 @@ dependencies = [ "wasmparser 0.219.1", ] -[[package]] -name = "wasmparser" -version = "0.216.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcdee6bea3619d311fb4b299721e89a986c3470f804b6d534340e412589028e3" -dependencies = [ - "bitflags 2.6.0", - "indexmap", -] - [[package]] name = "wasmparser" version = "0.218.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b09e46c7fceceaa72b2dd1a8a137ea7fd8f93dfaa69806010a709918e496c5dc" dependencies = [ - "bitflags 2.6.0", + "bitflags", ] [[package]] @@ -5886,35 +5953,56 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c771866898879073c53b565a6c7b49953795159836714ac56a5befb581227c5" dependencies = [ "ahash", - "bitflags 2.6.0", + "bitflags", "hashbrown 0.14.5", "indexmap", "semver", "serde", ] +[[package]] +name = "wasmparser" +version = "0.221.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8659e755615170cfe20da468865c989da78c5da16d8652e69a75acda02406a92" +dependencies = [ + "bitflags", + "indexmap", + "semver", +] + [[package]] name = "wast" -version = "219.0.1" +version = "221.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f79a9d9df79986a68689a6b40bcc8d5d40d807487b235bebc2ac69a242b54a1" +checksum = "9d8eb1933d493dd07484a255c3f52236123333f5befaa3be36182a50d393ec54" dependencies = [ "bumpalo", "leb128", "memchr", - "unicode-width 0.1.14", - "wasm-encoder 0.219.1", + "unicode-width 0.2.0", + "wasm-encoder 0.221.0", ] [[package]] name = "wat" -version = "1.219.1" +version = "1.221.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bc3cf014fb336883a411cd662f987abf6a1d2a27f2f0008616a0070bbf6bd0d" +checksum = "c813fd4e5b2b97242830b56e7b7dc5479bc17aaa8730109be35e61909af83993" dependencies = [ "wast", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "winapi" version = "0.3.9" @@ -5966,7 +6054,7 @@ dependencies = [ "rayon", "serde", "serde_json", - "syn 2.0.87", + "syn 2.0.90", "windows-metadata", ] @@ -5999,7 +6087,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -6010,7 +6098,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -6192,7 +6280,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad1673163c0cb14a6a19ddbf44dd4efe6f015ec1ebb8156710ac32501f19fba2" dependencies = [ "anyhow", - "bitflags 2.6.0", + "bitflags", "indexmap", "log", "serde", @@ -6222,6 +6310,12 @@ dependencies = [ "wasmparser 0.219.1", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + [[package]] name = "writeable" version = "0.5.5" @@ -6259,9 +6353,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ "serde", "stable_deref_trait", @@ -6271,13 +6365,13 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "synstructure", ] @@ -6299,27 +6393,27 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "zerofrom" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "synstructure", ] @@ -6342,5 +6436,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index b898cfec796..e40a2aa3612 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -42,7 +42,7 @@ tempfile = "3.2" thin-vec = "0.2.12" thorin-dwp = "0.8" tracing = "0.1" -wasm-encoder = "0.216.0" +wasm-encoder = "0.219" # tidy-alphabetical-end [target.'cfg(unix)'.dependencies] diff --git a/library/Cargo.lock b/library/Cargo.lock index f9b0af2c6e8..490c989300f 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -36,15 +36,15 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.18" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" [[package]] name = "cc" -version = "1.2.0" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8" +checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" dependencies = [ "shlex", ] @@ -403,9 +403,9 @@ dependencies = [ [[package]] name = "unwinding" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "637d511437df708cee34bdec7ba2f1548d256b7acf3ff20e0a1c559f9bf3a987" +checksum = "e2c6cb20f236dae10c69b0b45d82ef50af8b7e45c10e429e7901d26b49b4dbf3" dependencies = [ "compiler_builtins", "gimli 0.31.1", diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml index 3c172b2d956..15ed03ad5c2 100644 --- a/src/tools/run-make-support/Cargo.toml +++ b/src/tools/run-make-support/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" bstr = "1.6.0" object = "0.36.2" similar = "2.5.0" -wasmparser = { version = "0.216", default-features = false, features = ["std"] } +wasmparser = { version = "0.219", default-features = false, features = ["std"] } regex = "1.8" # 1.8 to avoid memchr 2.6.0, as 2.5.0 is pinned in the workspace gimli = "0.31.0" build_helper = { path = "../../build_helper" } diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock index 400eb7c5e0d..3d35779be90 100644 --- a/src/tools/rustbook/Cargo.lock +++ b/src/tools/rustbook/Cargo.lock @@ -47,9 +47,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.17" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -96,9 +96,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "autocfg" @@ -138,9 +138,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" +checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22" dependencies = [ "memchr", "regex-automata", @@ -161,9 +161,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.2.0" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8" +checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" dependencies = [ "shlex", ] @@ -190,9 +190,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" dependencies = [ "clap_builder", "clap_derive", @@ -200,9 +200,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" dependencies = [ "anstream", "anstyle", @@ -213,9 +213,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.36" +version = "4.5.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86bc73de94bc81e52f3bebec71bc4463e9748f7a59166663e32044669577b0e2" +checksum = "d9647a559c112175f17cf724dc72d3645680a883c58481332779192b0d8e7a01" dependencies = [ "clap", ] @@ -234,9 +234,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" [[package]] name = "colorchoice" @@ -252,9 +252,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -311,6 +311,17 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "doc-comment" version = "0.3.3" @@ -360,25 +371,25 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "fastrand" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "flate2" -version = "1.0.34" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", "miniz_oxide", @@ -456,9 +467,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" @@ -524,21 +535,150 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown", @@ -552,16 +692,17 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "a865e038f7f6ed956f788f0d7d60c541fff74c7bd74272c5d4cf15c63743e705" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -573,9 +714,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.161" +version = "0.2.167" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" [[package]] name = "libdbus-sys" @@ -602,6 +743,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + [[package]] name = "lock_api" version = "0.4.12" @@ -646,9 +793,9 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.4.42" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7624879735513024d323e7267a0b3a7176aceb0db537939beb4ee31d9e8945e3" +checksum = "fe1f98b8d66e537d2f0ba06e7dec4f44001deec539a2d18bfc102d6a86189148" dependencies = [ "ammonia", "anyhow", @@ -852,9 +999,9 @@ dependencies = [ [[package]] name = "pathdiff" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" [[package]] name = "percent-encoding" @@ -996,9 +1143,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -1120,9 +1267,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -1150,9 +1297,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.38" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ "bitflags 2.6.0", "errno", @@ -1190,18 +1337,18 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", @@ -1210,9 +1357,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -1258,6 +1405,12 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "string_cache" version = "0.8.7" @@ -1292,15 +1445,26 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.87" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "syntect" version = "5.2.0" @@ -1323,9 +1487,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", "fastrand", @@ -1347,9 +1511,9 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef" +checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9" dependencies = [ "rustix", "windows-sys 0.59.0", @@ -1363,18 +1527,18 @@ checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thiserror" -version = "1.0.66" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.66" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", @@ -1382,20 +1546,15 @@ dependencies = [ ] [[package]] -name = "tinyvec" -version = "1.8.0" +name = "tinystr" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ - "tinyvec_macros", + "displaydoc", + "zerovec", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "toml" version = "0.5.11" @@ -1463,26 +1622,11 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" -[[package]] -name = "unicode-bidi" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" - [[package]] name = "unicode-ident" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" - -[[package]] -name = "unicode-normalization" -version = "0.1.24" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-width" @@ -1492,9 +1636,9 @@ checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "url" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", @@ -1507,6 +1651,18 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -1537,9 +1693,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "d15e63b4482863c109d70a7b8706c1e364eb6ea449b201a76c5b89cedcec2d5c" dependencies = [ "cfg-if", "once_cell", @@ -1548,9 +1704,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "8d36ef12e3aaca16ddd3f67922bc63e48e953f126de60bd33ccc0101ef9998cd" dependencies = [ "bumpalo", "log", @@ -1563,9 +1719,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "705440e08b42d3e4b36de7d66c944be628d579796b8090bfa3471478a2260051" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1573,9 +1729,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d" dependencies = [ "proc-macro2", "quote", @@ -1586,9 +1742,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49" [[package]] name = "winapi" @@ -1721,6 +1877,42 @@ dependencies = [ "memchr", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -1741,3 +1933,46 @@ dependencies = [ "quote", "syn", ] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index e065f01ebba..493d9f5d5ec 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -12,7 +12,8 @@ use cargo_metadata::{Metadata, Package, PackageId}; #[rustfmt::skip] const LICENSES: &[&str] = &[ // tidy-alphabetical-start - "(MIT OR Apache-2.0) AND Unicode-DFS-2016", // unicode_ident + "(MIT OR Apache-2.0) AND Unicode-3.0", // unicode_ident (1.0.14) + "(MIT OR Apache-2.0) AND Unicode-DFS-2016", // unicode_ident (1.0.12) "0BSD OR MIT OR Apache-2.0", // adler license "0BSD", "Apache-2.0 / MIT", @@ -94,7 +95,6 @@ const EXCEPTIONS: ExceptionList = &[ ("dissimilar", "Apache-2.0"), // rustdoc, rustc_lexer (few tests) via expect-test, (dev deps) ("fluent-langneg", "Apache-2.0"), // rustc (fluent translations) ("foldhash", "Zlib"), // rustc - ("instant", "BSD-3-Clause"), // rustc_driver/tracing-subscriber/parking_lot ("mdbook", "MPL-2.0"), // mdbook ("option-ext", "MPL-2.0"), // cargo-miri (via `directories`) ("rustc_apfloat", "Apache-2.0 WITH LLVM-exception"), // rustc (license is the same as LLVM uses) -- cgit 1.4.1-3-g733a5 From 1c4657d3cd1cef28dfd89d8f3a3e1970487d2ee0 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 1 Dec 2024 18:18:19 +0100 Subject: compiletest: un-escape new-line in normalize replacement string --- src/tools/compiletest/src/header.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/tools') diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index fe4c5fdd8b5..0a54f17725e 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -1135,6 +1135,8 @@ fn parse_normalize_rule(header: &str) -> Option<(String, String)> { .captures(header)?; let regex = captures["regex"].to_owned(); let replacement = captures["replacement"].to_owned(); + // FIXME: Support escaped new-line in strings. + let replacement = replacement.replace("\\n", "\n"); Some((regex, replacement)) } -- cgit 1.4.1-3-g733a5 From 035777d47744faebde5de8d0406f64eb9f10f221 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Thu, 28 Nov 2024 17:06:26 -0800 Subject: Split unix-specific function into UnixFileDescription --- src/tools/miri/src/shims/files.rs | 54 +----------- src/tools/miri/src/shims/unix/fd.rs | 63 +++++++++++++- src/tools/miri/src/shims/unix/fs.rs | 87 ++++++++++--------- src/tools/miri/src/shims/unix/linux_like/epoll.rs | 9 +- .../miri/src/shims/unix/linux_like/eventfd.rs | 29 ++++--- src/tools/miri/src/shims/unix/mod.rs | 4 +- src/tools/miri/src/shims/unix/unnamed_socket.rs | 99 ++++++++++++---------- 7 files changed, 190 insertions(+), 155 deletions(-) (limited to 'src/tools') diff --git a/src/tools/miri/src/shims/files.rs b/src/tools/miri/src/shims/files.rs index 197ed726a1b..7f8b519e887 100644 --- a/src/tools/miri/src/shims/files.rs +++ b/src/tools/miri/src/shims/files.rs @@ -7,15 +7,9 @@ use std::rc::{Rc, Weak}; use rustc_abi::Size; +use crate::shims::unix::UnixFileDescription; use crate::*; -#[derive(Debug, Clone, Copy, Eq, PartialEq)] -pub(crate) enum FlockOp { - SharedLock { nonblocking: bool }, - ExclusiveLock { nonblocking: bool }, - Unlock, -} - /// Represents an open file description. pub trait FileDescription: std::fmt::Debug + Any { fn name(&self) -> &'static str; @@ -50,37 +44,6 @@ pub trait FileDescription: std::fmt::Debug + Any { throw_unsup_format!("cannot write to {}", self.name()); } - /// Reads as much as possible into the given buffer `ptr` from a given offset. - /// `len` indicates how many bytes we should try to read. - /// `dest` is where the return value should be stored: number of bytes read, or `-1` in case of error. - fn pread<'tcx>( - &self, - _communicate_allowed: bool, - _offset: u64, - _ptr: Pointer, - _len: usize, - _dest: &MPlaceTy<'tcx>, - _ecx: &mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx> { - throw_unsup_format!("cannot pread from {}", self.name()); - } - - /// Writes as much as possible from the given buffer `ptr` starting at a given offset. - /// `ptr` is the pointer to the user supplied read buffer. - /// `len` indicates how many bytes we should try to write. - /// `dest` is where the return value should be stored: number of bytes written, or `-1` in case of error. - fn pwrite<'tcx>( - &self, - _communicate_allowed: bool, - _ptr: Pointer, - _len: usize, - _offset: u64, - _dest: &MPlaceTy<'tcx>, - _ecx: &mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx> { - throw_unsup_format!("cannot pwrite to {}", self.name()); - } - /// Seeks to the given offset (which can be relative to the beginning, end, or current position). /// Returns the new position from the start of the stream. fn seek<'tcx>( @@ -99,25 +62,14 @@ pub trait FileDescription: std::fmt::Debug + Any { throw_unsup_format!("cannot close {}", self.name()); } - fn flock<'tcx>( - &self, - _communicate_allowed: bool, - _op: FlockOp, - ) -> InterpResult<'tcx, io::Result<()>> { - throw_unsup_format!("cannot flock {}", self.name()); - } - fn is_tty(&self, _communicate_allowed: bool) -> bool { // Most FDs are not tty's and the consequence of a wrong `false` are minor, // so we use a default impl here. false } - /// Check the readiness of file description. - fn get_epoll_ready_events<'tcx>( - &self, - ) -> InterpResult<'tcx, crate::shims::unix::linux::epoll::EpollReadyEvents> { - throw_unsup_format!("{}: epoll does not support this file description", self.name()); + fn as_unix(&self) -> &dyn UnixFileDescription { + panic!("Not a unix file descriptor: {}", self.name()); } } diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs index a9a24dd2958..e5dead1a263 100644 --- a/src/tools/miri/src/shims/unix/fd.rs +++ b/src/tools/miri/src/shims/unix/fd.rs @@ -1,16 +1,71 @@ //! General management of file descriptors, and support for //! standard file descriptors (stdin/stdout/stderr). +use std::io; use std::io::ErrorKind; use rustc_abi::Size; use crate::helpers::check_min_arg_count; -use crate::shims::files::FlockOp; +use crate::shims::files::FileDescription; use crate::shims::unix::linux_like::epoll::EpollReadyEvents; use crate::shims::unix::*; use crate::*; +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub(crate) enum FlockOp { + SharedLock { nonblocking: bool }, + ExclusiveLock { nonblocking: bool }, + Unlock, +} + +/// Represents unix-specific file descriptions. +pub trait UnixFileDescription: FileDescription { + /// Reads as much as possible into the given buffer `ptr` from a given offset. + /// `len` indicates how many bytes we should try to read. + /// `dest` is where the return value should be stored: number of bytes read, or `-1` in case of error. + fn pread<'tcx>( + &self, + _communicate_allowed: bool, + _offset: u64, + _ptr: Pointer, + _len: usize, + _dest: &MPlaceTy<'tcx>, + _ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx> { + throw_unsup_format!("cannot pread from {}", self.name()); + } + + /// Writes as much as possible from the given buffer `ptr` starting at a given offset. + /// `ptr` is the pointer to the user supplied read buffer. + /// `len` indicates how many bytes we should try to write. + /// `dest` is where the return value should be stored: number of bytes written, or `-1` in case of error. + fn pwrite<'tcx>( + &self, + _communicate_allowed: bool, + _ptr: Pointer, + _len: usize, + _offset: u64, + _dest: &MPlaceTy<'tcx>, + _ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx> { + throw_unsup_format!("cannot pwrite to {}", self.name()); + } + + fn flock<'tcx>( + &self, + _communicate_allowed: bool, + _op: FlockOp, + ) -> InterpResult<'tcx, io::Result<()>> { + throw_unsup_format!("cannot flock {}", self.name()); + } + + /// Check the readiness of file description. + fn get_epoll_ready_events<'tcx>(&self) -> InterpResult<'tcx, EpollReadyEvents> { + throw_unsup_format!("{}: epoll does not support this file description", self.name()); + } +} + impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn dup(&mut self, old_fd_num: i32) -> InterpResult<'tcx, Scalar> { @@ -66,7 +121,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { throw_unsup_format!("unsupported flags {:#x}", op); }; - let result = fd.flock(this.machine.communicate(), parsed_op)?; + let result = fd.as_unix().flock(this.machine.communicate(), parsed_op)?; drop(fd); // return `0` if flock is successful let result = result.map(|()| 0i32); @@ -196,7 +251,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let Ok(offset) = u64::try_from(offset) else { return this.set_last_error_and_return(LibcError("EINVAL"), dest); }; - fd.pread(communicate, offset, buf, count, dest, this)? + fd.as_unix().pread(communicate, offset, buf, count, dest, this)? } }; interp_ok(()) @@ -236,7 +291,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let Ok(offset) = u64::try_from(offset) else { return this.set_last_error_and_return(LibcError("EINVAL"), dest); }; - fd.pwrite(communicate, buf, count, offset, dest, this)? + fd.as_unix().pwrite(communicate, buf, count, offset, dest, this)? } }; interp_ok(()) diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index f363627da93..3b301b10e34 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -13,8 +13,9 @@ use rustc_data_structures::fx::FxHashMap; use self::shims::time::system_time_to_duration; use crate::helpers::check_min_arg_count; -use crate::shims::files::{EvalContextExt as _, FileDescription, FileDescriptionRef, FlockOp}; +use crate::shims::files::{EvalContextExt as _, FileDescription, FileDescriptionRef}; use crate::shims::os_str::bytes_to_os_str; +use crate::shims::unix::fd::{FlockOp, UnixFileDescription}; use crate::*; #[derive(Debug)] @@ -64,6 +65,51 @@ impl FileDescription for FileHandle { } } + fn seek<'tcx>( + &self, + communicate_allowed: bool, + offset: SeekFrom, + ) -> InterpResult<'tcx, io::Result> { + assert!(communicate_allowed, "isolation should have prevented even opening a file"); + interp_ok((&mut &self.file).seek(offset)) + } + + fn close<'tcx>( + self: Box, + communicate_allowed: bool, + _ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx, io::Result<()>> { + assert!(communicate_allowed, "isolation should have prevented even opening a file"); + // We sync the file if it was opened in a mode different than read-only. + if self.writable { + // `File::sync_all` does the checks that are done when closing a file. We do this to + // to handle possible errors correctly. + let result = self.file.sync_all(); + // Now we actually close the file and return the result. + drop(*self); + interp_ok(result) + } else { + // We drop the file, this closes it but ignores any errors + // produced when closing it. This is done because + // `File::sync_all` cannot be done over files like + // `/dev/urandom` which are read-only. Check + // https://github.com/rust-lang/miri/issues/999#issuecomment-568920439 + // for a deeper discussion. + drop(*self); + interp_ok(Ok(())) + } + } + + fn is_tty(&self, communicate_allowed: bool) -> bool { + communicate_allowed && self.file.is_terminal() + } + + fn as_unix(&self) -> &dyn UnixFileDescription { + self + } +} + +impl UnixFileDescription for FileHandle { fn pread<'tcx>( &self, communicate_allowed: bool, @@ -126,41 +172,6 @@ impl FileDescription for FileHandle { } } - fn seek<'tcx>( - &self, - communicate_allowed: bool, - offset: SeekFrom, - ) -> InterpResult<'tcx, io::Result> { - assert!(communicate_allowed, "isolation should have prevented even opening a file"); - interp_ok((&mut &self.file).seek(offset)) - } - - fn close<'tcx>( - self: Box, - communicate_allowed: bool, - _ecx: &mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx, io::Result<()>> { - assert!(communicate_allowed, "isolation should have prevented even opening a file"); - // We sync the file if it was opened in a mode different than read-only. - if self.writable { - // `File::sync_all` does the checks that are done when closing a file. We do this to - // to handle possible errors correctly. - let result = self.file.sync_all(); - // Now we actually close the file and return the result. - drop(*self); - interp_ok(result) - } else { - // We drop the file, this closes it but ignores any errors - // produced when closing it. This is done because - // `File::sync_all` cannot be done over files like - // `/dev/urandom` which are read-only. Check - // https://github.com/rust-lang/miri/issues/999#issuecomment-568920439 - // for a deeper discussion. - drop(*self); - interp_ok(Ok(())) - } - } - fn flock<'tcx>( &self, communicate_allowed: bool, @@ -255,10 +266,6 @@ impl FileDescription for FileHandle { compile_error!("flock is supported only on UNIX and Windows hosts"); } } - - fn is_tty(&self, communicate_allowed: bool) -> bool { - communicate_allowed && self.file.is_terminal() - } } impl<'tcx> EvalContextExtPrivate<'tcx> for crate::MiriInterpCx<'tcx> {} diff --git a/src/tools/miri/src/shims/unix/linux_like/epoll.rs b/src/tools/miri/src/shims/unix/linux_like/epoll.rs index d0317132c6c..5b240351c20 100644 --- a/src/tools/miri/src/shims/unix/linux_like/epoll.rs +++ b/src/tools/miri/src/shims/unix/linux_like/epoll.rs @@ -6,6 +6,7 @@ use std::time::Duration; use crate::concurrency::VClock; use crate::shims::files::{FdId, FileDescription, FileDescriptionRef, WeakFileDescriptionRef}; +use crate::shims::unix::UnixFileDescription; use crate::*; /// An `Epoll` file descriptor connects file handles and epoll events @@ -151,8 +152,14 @@ impl FileDescription for Epoll { ) -> InterpResult<'tcx, io::Result<()>> { interp_ok(Ok(())) } + + fn as_unix(&self) -> &dyn UnixFileDescription { + self + } } +impl UnixFileDescription for Epoll {} + /// The table of all EpollEventInterest. /// The BTreeMap key is the FdId of an active file description registered with /// any epoll instance. The value is a list of EpollEventInterest associated @@ -594,7 +601,7 @@ fn check_and_update_one_event_interest<'tcx>( ecx: &MiriInterpCx<'tcx>, ) -> InterpResult<'tcx, bool> { // Get the bitmask of ready events for a file description. - let ready_events_bitmask = fd_ref.get_epoll_ready_events()?.get_event_bitmask(ecx); + let ready_events_bitmask = fd_ref.as_unix().get_epoll_ready_events()?.get_event_bitmask(ecx); let epoll_event_interest = interest.borrow(); // This checks if any of the events specified in epoll_event_interest.events // match those in ready_events. diff --git a/src/tools/miri/src/shims/unix/linux_like/eventfd.rs b/src/tools/miri/src/shims/unix/linux_like/eventfd.rs index 5b51b5a0f09..4bbe417ea8d 100644 --- a/src/tools/miri/src/shims/unix/linux_like/eventfd.rs +++ b/src/tools/miri/src/shims/unix/linux_like/eventfd.rs @@ -5,6 +5,7 @@ use std::io::ErrorKind; use crate::concurrency::VClock; use crate::shims::files::{FileDescription, FileDescriptionRef, WeakFileDescriptionRef}; +use crate::shims::unix::UnixFileDescription; use crate::shims::unix::linux_like::epoll::{EpollReadyEvents, EvalContextExt as _}; use crate::*; @@ -36,17 +37,6 @@ impl FileDescription for Event { "event" } - fn get_epoll_ready_events<'tcx>(&self) -> InterpResult<'tcx, EpollReadyEvents> { - // We only check the status of EPOLLIN and EPOLLOUT flags for eventfd. If other event flags - // need to be supported in the future, the check should be added here. - - interp_ok(EpollReadyEvents { - epollin: self.counter.get() != 0, - epollout: self.counter.get() != MAX_COUNTER, - ..EpollReadyEvents::new() - }) - } - fn close<'tcx>( self: Box, _communicate_allowed: bool, @@ -120,6 +110,23 @@ impl FileDescription for Event { let weak_eventfd = self_ref.downgrade(); eventfd_write(num, buf_place, dest, weak_eventfd, ecx) } + + fn as_unix(&self) -> &dyn UnixFileDescription { + self + } +} + +impl UnixFileDescription for Event { + fn get_epoll_ready_events<'tcx>(&self) -> InterpResult<'tcx, EpollReadyEvents> { + // We only check the status of EPOLLIN and EPOLLOUT flags for eventfd. If other event flags + // need to be supported in the future, the check should be added here. + + interp_ok(EpollReadyEvents { + epollin: self.counter.get() != 0, + epollout: self.counter.get() != MAX_COUNTER, + ..EpollReadyEvents::new() + }) + } } impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} diff --git a/src/tools/miri/src/shims/unix/mod.rs b/src/tools/miri/src/shims/unix/mod.rs index fea5bc959c6..660e4ded5cd 100644 --- a/src/tools/miri/src/shims/unix/mod.rs +++ b/src/tools/miri/src/shims/unix/mod.rs @@ -10,14 +10,14 @@ mod unnamed_socket; mod android; mod freebsd; -mod linux; +pub mod linux; mod linux_like; mod macos; mod solarish; // All the Unix-specific extension traits pub use self::env::{EvalContextExt as _, UnixEnvVars}; -pub use self::fd::EvalContextExt as _; +pub use self::fd::{EvalContextExt as _, UnixFileDescription}; pub use self::fs::{DirTable, EvalContextExt as _}; pub use self::linux_like::epoll::EpollInterestTable; pub use self::mem::EvalContextExt as _; diff --git a/src/tools/miri/src/shims/unix/unnamed_socket.rs b/src/tools/miri/src/shims/unix/unnamed_socket.rs index 5d2b767fe8b..24304c0c04b 100644 --- a/src/tools/miri/src/shims/unix/unnamed_socket.rs +++ b/src/tools/miri/src/shims/unix/unnamed_socket.rs @@ -13,6 +13,7 @@ use crate::concurrency::VClock; use crate::shims::files::{ EvalContextExt as _, FileDescription, FileDescriptionRef, WeakFileDescriptionRef, }; +use crate::shims::unix::UnixFileDescription; use crate::shims::unix::linux_like::epoll::{EpollReadyEvents, EvalContextExt as _}; use crate::*; @@ -61,52 +62,6 @@ impl FileDescription for AnonSocket { "socketpair" } - fn get_epoll_ready_events<'tcx>(&self) -> InterpResult<'tcx, EpollReadyEvents> { - // We only check the status of EPOLLIN, EPOLLOUT, EPOLLHUP and EPOLLRDHUP flags. - // If other event flags need to be supported in the future, the check should be added here. - - let mut epoll_ready_events = EpollReadyEvents::new(); - - // Check if it is readable. - if let Some(readbuf) = &self.readbuf { - if !readbuf.borrow().buf.is_empty() { - epoll_ready_events.epollin = true; - } - } else { - // Without a read buffer, reading never blocks, so we are always ready. - epoll_ready_events.epollin = true; - } - - // Check if is writable. - if let Some(peer_fd) = self.peer_fd().upgrade() { - if let Some(writebuf) = &peer_fd.downcast::().unwrap().readbuf { - let data_size = writebuf.borrow().buf.len(); - let available_space = MAX_SOCKETPAIR_BUFFER_CAPACITY.strict_sub(data_size); - if available_space != 0 { - epoll_ready_events.epollout = true; - } - } else { - // Without a write buffer, writing never blocks. - epoll_ready_events.epollout = true; - } - } else { - // Peer FD has been closed. This always sets both the RDHUP and HUP flags - // as we do not support `shutdown` that could be used to partially close the stream. - epoll_ready_events.epollrdhup = true; - epoll_ready_events.epollhup = true; - // Since the peer is closed, even if no data is available reads will return EOF and - // writes will return EPIPE. In other words, they won't block, so we mark this as ready - // for read and write. - epoll_ready_events.epollin = true; - epoll_ready_events.epollout = true; - // If there is data lost in peer_fd, set EPOLLERR. - if self.peer_lost_data.get() { - epoll_ready_events.epollerr = true; - } - } - interp_ok(epoll_ready_events) - } - fn close<'tcx>( self: Box, _communicate_allowed: bool, @@ -211,6 +166,10 @@ impl FileDescription for AnonSocket { } anonsocket_write(available_space, &peer_fd, ptr, len, dest, ecx) } + + fn as_unix(&self) -> &dyn UnixFileDescription { + self + } } /// Write to AnonSocket based on the space available and return the written byte size. @@ -290,6 +249,54 @@ fn anonsocket_read<'tcx>( ecx.return_read_success(ptr, bytes, actual_read_size, dest) } +impl UnixFileDescription for AnonSocket { + fn get_epoll_ready_events<'tcx>(&self) -> InterpResult<'tcx, EpollReadyEvents> { + // We only check the status of EPOLLIN, EPOLLOUT, EPOLLHUP and EPOLLRDHUP flags. + // If other event flags need to be supported in the future, the check should be added here. + + let mut epoll_ready_events = EpollReadyEvents::new(); + + // Check if it is readable. + if let Some(readbuf) = &self.readbuf { + if !readbuf.borrow().buf.is_empty() { + epoll_ready_events.epollin = true; + } + } else { + // Without a read buffer, reading never blocks, so we are always ready. + epoll_ready_events.epollin = true; + } + + // Check if is writable. + if let Some(peer_fd) = self.peer_fd().upgrade() { + if let Some(writebuf) = &peer_fd.downcast::().unwrap().readbuf { + let data_size = writebuf.borrow().buf.len(); + let available_space = MAX_SOCKETPAIR_BUFFER_CAPACITY.strict_sub(data_size); + if available_space != 0 { + epoll_ready_events.epollout = true; + } + } else { + // Without a write buffer, writing never blocks. + epoll_ready_events.epollout = true; + } + } else { + // Peer FD has been closed. This always sets both the RDHUP and HUP flags + // as we do not support `shutdown` that could be used to partially close the stream. + epoll_ready_events.epollrdhup = true; + epoll_ready_events.epollhup = true; + // Since the peer is closed, even if no data is available reads will return EOF and + // writes will return EPIPE. In other words, they won't block, so we mark this as ready + // for read and write. + epoll_ready_events.epollin = true; + epoll_ready_events.epollout = true; + // If there is data lost in peer_fd, set EPOLLERR. + if self.peer_lost_data.get() { + epoll_ready_events.epollerr = true; + } + } + interp_ok(epoll_ready_events) + } +} + impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { /// For more information on the arguments see the socketpair manpage: -- cgit 1.4.1-3-g733a5 From 244249e464742e5d3d0193b7ed4e3505d8204684 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Thu, 28 Nov 2024 17:18:42 -0800 Subject: Make metadata a FileDescription operation --- src/tools/miri/src/shims/files.rs | 10 +++++++--- src/tools/miri/src/shims/unix/fs.rs | 18 +++++++----------- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src/tools') diff --git a/src/tools/miri/src/shims/files.rs b/src/tools/miri/src/shims/files.rs index 7f8b519e887..f673b834be2 100644 --- a/src/tools/miri/src/shims/files.rs +++ b/src/tools/miri/src/shims/files.rs @@ -1,9 +1,9 @@ use std::any::Any; use std::collections::BTreeMap; -use std::io; use std::io::{IsTerminal, Read, SeekFrom, Write}; use std::ops::Deref; use std::rc::{Rc, Weak}; +use std::{fs, io}; use rustc_abi::Size; @@ -62,6 +62,10 @@ pub trait FileDescription: std::fmt::Debug + Any { throw_unsup_format!("cannot close {}", self.name()); } + fn metadata<'tcx>(&self) -> InterpResult<'tcx, io::Result> { + throw_unsup_format!("obtaining metadata is only supported on file-backed file descriptors"); + } + fn is_tty(&self, _communicate_allowed: bool) -> bool { // Most FDs are not tty's and the consequence of a wrong `false` are minor, // so we use a default impl here. @@ -273,8 +277,8 @@ impl VisitProvenance for WeakFileDescriptionRef { /// A unique id for file descriptions. While we could use the address, considering that /// is definitely unique, the address would expose interpreter internal state when used -/// for sorting things. So instead we generate a unique id per file description that stays -/// the same even if a file descriptor is duplicated and gets a new integer file descriptor. +/// for sorting things. So instead we generate a unique id per file description is the name +/// for all `dup`licates and is never reused. #[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Ord, PartialOrd)] pub struct FdId(usize); diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 3b301b10e34..b41a4d2246f 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -2,7 +2,8 @@ use std::borrow::Cow; use std::fs::{ - DirBuilder, File, FileType, OpenOptions, ReadDir, read_dir, remove_dir, remove_file, rename, + DirBuilder, File, FileType, Metadata, OpenOptions, ReadDir, read_dir, remove_dir, remove_file, + rename, }; use std::io::{self, ErrorKind, IsTerminal, Read, Seek, SeekFrom, Write}; use std::path::{Path, PathBuf}; @@ -100,6 +101,10 @@ impl FileDescription for FileHandle { } } + fn metadata<'tcx>(&self) -> InterpResult<'tcx, io::Result> { + interp_ok(self.file.metadata()) + } + fn is_tty(&self, communicate_allowed: bool) -> bool { communicate_allowed && self.file.is_terminal() } @@ -1698,16 +1703,7 @@ impl FileMetadata { return interp_ok(Err(LibcError("EBADF"))); }; - let file = &fd - .downcast::() - .ok_or_else(|| { - err_unsup_format!( - "obtaining metadata is only supported on file-backed file descriptors" - ) - })? - .file; - - let metadata = file.metadata(); + let metadata = fd.metadata()?; drop(fd); FileMetadata::from_meta(ecx, metadata) } -- cgit 1.4.1-3-g733a5 From 2f17ea0ff53ddedfa659b1173e5bbbd57fb0231d Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 1 Dec 2024 21:47:20 -0500 Subject: Remove `//@ compare-output-lines-by-subset` There was only ever one test which used this flag, and it was removed in https://github.com/rust-lang/rust/pull/132244. I think this is a bad flag that should never have been added; comparing by subset makes the test failures extremely hard to debug. Any test that needs complicated output filtering like this should just use run-make instead. Note that this does not remove the underlying comparison code, because it's still used if `runner` is set. I don't quite understand what's going on there, but since we still test on other platforms and in CI that the full output is accurate, I think it will be easier to debug than a test that uses compare-by-subset unconditionally. --- src/tools/compiletest/src/directive-list.rs | 1 - src/tools/compiletest/src/header.rs | 10 ---------- src/tools/compiletest/src/runtest.rs | 11 ++++------- 3 files changed, 4 insertions(+), 18 deletions(-) (limited to 'src/tools') diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index 952533e904c..f3f76971464 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -17,7 +17,6 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "check-run-results", "check-stdout", "check-test-line-numbers-match", - "compare-output-lines-by-subset", "compile-flags", "doc-flags", "dont-check-compiler-stderr", diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index fe4c5fdd8b5..73e56cfac8f 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -115,9 +115,6 @@ pub struct TestProps { pub dont_check_compiler_stdout: bool, // For UI tests, allows compiler to generate arbitrary output to stderr pub dont_check_compiler_stderr: bool, - // When checking the output of stdout or stderr check - // that the lines of expected output are a subset of the actual output. - pub compare_output_lines_by_subset: bool, // Don't force a --crate-type=dylib flag on the command line // // Set this for example if you have an auxiliary test file that contains @@ -240,7 +237,6 @@ mod directives { pub const KNOWN_BUG: &'static str = "known-bug"; pub const TEST_MIR_PASS: &'static str = "test-mir-pass"; pub const REMAP_SRC_BASE: &'static str = "remap-src-base"; - pub const COMPARE_OUTPUT_LINES_BY_SUBSET: &'static str = "compare-output-lines-by-subset"; pub const LLVM_COV_FLAGS: &'static str = "llvm-cov-flags"; pub const FILECHECK_FLAGS: &'static str = "filecheck-flags"; pub const NO_AUTO_CHECK_CFG: &'static str = "no-auto-check-cfg"; @@ -274,7 +270,6 @@ impl TestProps { check_run_results: false, dont_check_compiler_stdout: false, dont_check_compiler_stderr: false, - compare_output_lines_by_subset: false, no_prefer_dynamic: false, pretty_mode: "normal".to_string(), pretty_compare_only: false, @@ -550,11 +545,6 @@ impl TestProps { |s| s.trim().to_string(), ); config.set_name_directive(ln, REMAP_SRC_BASE, &mut self.remap_src_base); - config.set_name_directive( - ln, - COMPARE_OUTPUT_LINES_BY_SUBSET, - &mut self.compare_output_lines_by_subset, - ); if let Some(flags) = config.parse_name_value_directive(ln, LLVM_COV_FLAGS) { self.llvm_cov_flags.extend(split_flags(&flags)); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 93e5980f1f5..7be9e2f2d57 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2541,13 +2541,10 @@ impl<'test> TestCx<'test> { return 0; } - // If `compare-output-lines-by-subset` is not explicitly enabled then - // auto-enable it when a `runner` is in use since wrapper tools might - // provide extra output on failure, for example a WebAssembly runtime - // might print the stack trace of an `unreachable` instruction by - // default. - let compare_output_by_lines = - self.props.compare_output_lines_by_subset || self.config.runner.is_some(); + // Wrapper tools set by `runner` might provide extra output on failure, + // for example a WebAssembly runtime might print the stack trace of an + // `unreachable` instruction by default. + let compare_output_by_lines = self.config.runner.is_some(); let tmp; let (expected, actual): (&str, &str) = if compare_output_by_lines { -- cgit 1.4.1-3-g733a5 From 99c232223f8330debc199f616308bc559b38c361 Mon Sep 17 00:00:00 2001 From: "许杰友 Jieyou Xu (Joe)" <39484203+jieyouxu@users.noreply.github.com> Date: Mon, 2 Dec 2024 14:48:01 +0800 Subject: Add `needs-target-has-atomic` directive Before this commit, the test writer has to specify platforms and architectures by hand for targets that have differing atomic width support. `#[cfg(target_has_atomic)]` is not quite the same because (1) you may have to specify additional matchers manually which has to be maintained individually, and (2) the `#[cfg]` blocks does not communicate to compiletest that a test would be ignored for a given target. This commit implements a `//@ needs-target-has-atomic` directive which admits a comma-separated list of required atomic widths that the target must satisfy in order for the test to run. ``` //@ needs-target-has-atomic: 8, 16, ptr ``` See . Co-authored-by: kei519 --- src/tools/compiletest/src/common.rs | 22 ++++++++++++- src/tools/compiletest/src/directive-list.rs | 1 + src/tools/compiletest/src/header/needs.rs | 51 ++++++++++++++++++++++++++--- src/tools/compiletest/src/header/tests.rs | 37 +++++++++++++++++++++ 4 files changed, 106 insertions(+), 5 deletions(-) (limited to 'src/tools') diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index e6fbba943a4..36f876bcdc6 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::{BTreeSet, HashMap, HashSet}; use std::ffi::OsString; use std::path::{Path, PathBuf}; use std::process::Command; @@ -486,6 +486,9 @@ impl Config { } } +/// Known widths of `target_has_atomic`. +pub const KNOWN_TARGET_HAS_ATOMIC_WIDTHS: &[&str] = &["8", "16", "32", "64", "128", "ptr"]; + #[derive(Debug, Clone)] pub struct TargetCfgs { pub current: TargetCfg, @@ -611,6 +614,17 @@ impl TargetCfgs { ("panic", Some("abort")) => cfg.panic = PanicStrategy::Abort, ("panic", Some("unwind")) => cfg.panic = PanicStrategy::Unwind, ("panic", other) => panic!("unexpected value for panic cfg: {other:?}"), + + ("target_has_atomic", Some(width)) + if KNOWN_TARGET_HAS_ATOMIC_WIDTHS.contains(&width) => + { + cfg.target_has_atomic.insert(width.to_string()); + } + ("target_has_atomic", Some(other)) => { + panic!("unexpected value for `target_has_atomic` cfg: {other:?}") + } + // Nightly-only std-internal impl detail. + ("target_has_atomic", None) => {} _ => {} } } @@ -645,6 +659,12 @@ pub struct TargetCfg { pub(crate) xray: bool, #[serde(default = "default_reloc_model")] pub(crate) relocation_model: String, + + // Not present in target cfg json output, additional derived information. + #[serde(skip)] + /// Supported target atomic widths: e.g. `8` to `128` or `ptr`. This is derived from the builtin + /// `target_has_atomic` `cfg`s e.g. `target_has_atomic="8"`. + pub(crate) target_has_atomic: BTreeSet, } impl TargetCfg { diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index 952533e904c..c7e8d4b58a5 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -154,6 +154,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "needs-sanitizer-thread", "needs-std-debug-assertions", "needs-symlink", + "needs-target-has-atomic", "needs-threads", "needs-unwind", "needs-wasmtime", diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index 77570c58db5..e19dcd992fc 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -1,4 +1,4 @@ -use crate::common::{Config, Sanitizer}; +use crate::common::{Config, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer}; use crate::header::{IgnoreDecision, llvm_has_libzstd}; pub(super) fn handle_needs( @@ -171,11 +171,54 @@ pub(super) fn handle_needs( }, ]; - let (name, comment) = match ln.split_once([':', ' ']) { - Some((name, comment)) => (name, Some(comment)), + let (name, rest) = match ln.split_once([':', ' ']) { + Some((name, rest)) => (name, Some(rest)), None => (ln, None), }; + // FIXME(jieyouxu): tighten up this parsing to reject using both `:` and ` ` as means to + // delineate value. + if name == "needs-target-has-atomic" { + let Some(rest) = rest else { + return IgnoreDecision::Error { + message: "expected `needs-target-has-atomic` to have a comma-separated list of atomic widths".to_string(), + }; + }; + + // Expect directive value to be a list of comma-separated atomic widths. + let specified_widths = rest + .split(',') + .map(|width| width.trim()) + .map(ToString::to_string) + .collect::>(); + + for width in &specified_widths { + if !KNOWN_TARGET_HAS_ATOMIC_WIDTHS.contains(&width.as_str()) { + return IgnoreDecision::Error { + message: format!( + "unknown width specified in `needs-target-has-atomic`: `{width}` is not a \ + known `target_has_atomic_width`, known values are `{:?}`", + KNOWN_TARGET_HAS_ATOMIC_WIDTHS + ), + }; + } + } + + let satisfies_all_specified_widths = specified_widths + .iter() + .all(|specified| config.target_cfg().target_has_atomic.contains(specified)); + if satisfies_all_specified_widths { + return IgnoreDecision::Continue; + } else { + return IgnoreDecision::Ignore { + reason: format!( + "skipping test as target does not support all of the required `target_has_atomic` widths `{:?}`", + specified_widths + ), + }; + } + } + if !name.starts_with("needs-") { return IgnoreDecision::Continue; } @@ -193,7 +236,7 @@ pub(super) fn handle_needs( break; } else { return IgnoreDecision::Ignore { - reason: if let Some(comment) = comment { + reason: if let Some(comment) = rest { format!("{} ({})", need.ignore_reason, comment.trim()) } else { need.ignore_reason.into() diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 4d75c38dd32..cd7c6f8361e 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -787,3 +787,40 @@ fn test_not_trailing_directive() { run_path(&mut poisoned, Path::new("a.rs"), b"//@ revisions: incremental"); assert!(!poisoned); } + +#[test] +fn test_needs_target_has_atomic() { + use std::collections::BTreeSet; + + // `x86_64-unknown-linux-gnu` supports `["8", "16", "32", "64", "ptr"]` but not `128`. + + let config = cfg().target("x86_64-unknown-linux-gnu").build(); + // Expectation sanity check. + assert_eq!( + config.target_cfg().target_has_atomic, + BTreeSet::from([ + "8".to_string(), + "16".to_string(), + "32".to_string(), + "64".to_string(), + "ptr".to_string() + ]), + "expected `x86_64-unknown-linux-gnu` to not have 128-bit atomic support" + ); + + assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 8")); + assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 16")); + assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 32")); + assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 64")); + assert!(!check_ignore(&config, "//@ needs-target-has-atomic: ptr")); + + assert!(check_ignore(&config, "//@ needs-target-has-atomic: 128")); + + assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 8,16,32,64,ptr")); + + assert!(check_ignore(&config, "//@ needs-target-has-atomic: 8,16,32,64,ptr,128")); + + // Check whitespace between widths is permitted. + assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 8, ptr")); + assert!(check_ignore(&config, "//@ needs-target-has-atomic: 8, ptr, 128")); +} -- cgit 1.4.1-3-g733a5 From 778321d1559cfbfcf1868165b053cf73298dadfb Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 2 Dec 2024 10:06:26 +0000 Subject: Change `AttrArgs::Eq` into a struct variant --- compiler/rustc_ast/src/ast.rs | 22 +++++++++++----------- compiler/rustc_ast/src/attr/mod.rs | 12 +++++++----- compiler/rustc_ast/src/mut_visit.rs | 4 ++-- compiler/rustc_ast/src/visit.rs | 4 ++-- compiler/rustc_ast_lowering/src/lib.rs | 6 +++--- compiler/rustc_ast_pretty/src/pprust/state.rs | 4 ++-- compiler/rustc_expand/src/expand.rs | 2 +- compiler/rustc_parse/src/parser/mod.rs | 2 +- compiler/rustc_parse/src/validate_attr.rs | 8 +++++--- compiler/rustc_resolve/src/rustdoc.rs | 2 +- .../src/error_reporting/traits/on_unimplemented.rs | 4 ++-- src/librustdoc/clean/mod.rs | 2 +- .../src/attrs/should_panic_without_expect.rs | 2 +- .../src/doc/include_in_doc_without_cfg.rs | 2 +- .../clippy/clippy_lints/src/large_include_file.rs | 2 +- src/tools/clippy/clippy_utils/src/ast_utils.rs | 4 ++-- 16 files changed, 43 insertions(+), 39 deletions(-) (limited to 'src/tools') diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 56b20e0ad89..2ab63f5fb79 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1733,12 +1733,12 @@ pub enum AttrArgs { /// Delimited arguments: `#[attr()/[]/{}]`. Delimited(DelimArgs), /// Arguments of a key-value attribute: `#[attr = "value"]`. - Eq( + Eq { /// Span of the `=` token. - Span, - /// The "value". - AttrArgsEq, - ), + eq_span: Span, + + value: AttrArgsEq, + }, } // The RHS of an `AttrArgs::Eq` starts out as an expression. Once macro @@ -1755,8 +1755,8 @@ impl AttrArgs { match self { AttrArgs::Empty => None, AttrArgs::Delimited(args) => Some(args.dspan.entire()), - AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => Some(eq_span.to(expr.span)), - AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => { + AttrArgs::Eq { eq_span, value: AttrArgsEq::Ast(expr) } => Some(eq_span.to(expr.span)), + AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { unreachable!("in literal form when getting span: {:?}", lit); } } @@ -1768,8 +1768,8 @@ impl AttrArgs { match self { AttrArgs::Empty => TokenStream::default(), AttrArgs::Delimited(args) => args.tokens.clone(), - AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => TokenStream::from_ast(expr), - AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => { + AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => TokenStream::from_ast(expr), + AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { unreachable!("in literal form when getting inner tokens: {:?}", lit) } } @@ -1785,10 +1785,10 @@ where match self { AttrArgs::Empty => {} AttrArgs::Delimited(args) => args.hash_stable(ctx, hasher), - AttrArgs::Eq(_eq_span, AttrArgsEq::Ast(expr)) => { + AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => { unreachable!("hash_stable {:?}", expr); } - AttrArgs::Eq(eq_span, AttrArgsEq::Hir(lit)) => { + AttrArgs::Eq { eq_span, value: AttrArgsEq::Hir(lit) } => { eq_span.hash_stable(ctx, hasher); lit.hash_stable(ctx, hasher); } diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 888b13efa31..0d79cadef34 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -250,7 +250,7 @@ impl AttrItem { AttrArgs::Delimited(args) if args.delim == Delimiter::Parenthesis => { MetaItemKind::list_from_tokens(args.tokens.clone()) } - AttrArgs::Delimited(_) | AttrArgs::Eq(..) | AttrArgs::Empty => None, + AttrArgs::Delimited(_) | AttrArgs::Eq { .. } | AttrArgs::Empty => None, } } @@ -268,7 +268,7 @@ impl AttrItem { /// ``` fn value_str(&self) -> Option { match &self.args { - AttrArgs::Eq(_, args) => args.value_str(), + AttrArgs::Eq { value, .. } => value.value_str(), AttrArgs::Delimited(_) | AttrArgs::Empty => None, } } @@ -492,7 +492,7 @@ impl MetaItemKind { MetaItemKind::list_from_tokens(tokens.clone()).map(MetaItemKind::List) } AttrArgs::Delimited(..) => None, - AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => match expr.kind { + AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => match expr.kind { ExprKind::Lit(token_lit) => { // Turn failures to `None`, we'll get parse errors elsewhere. MetaItemLit::from_token_lit(token_lit, expr.span) @@ -501,7 +501,9 @@ impl MetaItemKind { } _ => None, }, - AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => Some(MetaItemKind::NameValue(lit.clone())), + AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { + Some(MetaItemKind::NameValue(lit.clone())) + } } } } @@ -702,7 +704,7 @@ pub fn mk_attr_name_value_str( tokens: None, }); let path = Path::from_ident(Ident::new(name, span)); - let args = AttrArgs::Eq(span, AttrArgsEq::Ast(expr)); + let args = AttrArgs::Eq { eq_span: span, value: AttrArgsEq::Ast(expr) }; mk_attr(g, style, unsafety, path, args, span) } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 0aceed45028..55434f232fe 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -451,11 +451,11 @@ fn visit_attr_args(vis: &mut T, args: &mut AttrArgs) { match args { AttrArgs::Empty => {} AttrArgs::Delimited(args) => visit_delim_args(vis, args), - AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => { + AttrArgs::Eq { eq_span, value: AttrArgsEq::Ast(expr) } => { vis.visit_expr(expr); vis.visit_span(eq_span); } - AttrArgs::Eq(_eq_span, AttrArgsEq::Hir(lit)) => { + AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { unreachable!("in literal form when visiting mac args eq: {:?}", lit) } } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 718397e8ca0..e92b7ac712a 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -1273,8 +1273,8 @@ pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) - match args { AttrArgs::Empty => {} AttrArgs::Delimited(_args) => {} - AttrArgs::Eq(_eq_span, AttrArgsEq::Ast(expr)) => try_visit!(visitor.visit_expr(expr)), - AttrArgs::Eq(_eq_span, AttrArgsEq::Hir(lit)) => { + AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => try_visit!(visitor.visit_expr(expr)), + AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { unreachable!("in literal form when walking mac args eq: {:?}", lit) } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 96546239f4c..6b67c256fc2 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -889,7 +889,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // This is an inert key-value attribute - it will never be visible to macros // after it gets lowered to HIR. Therefore, we can extract literals to handle // nonterminals in `#[doc]` (e.g. `#[doc = $e]`). - AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => { + &AttrArgs::Eq { eq_span, value: AttrArgsEq::Ast(ref expr) } => { // In valid code the value always ends up as a single literal. Otherwise, a dummy // literal suffices because the error is handled elsewhere. let lit = if let ExprKind::Lit(token_lit) = expr.kind @@ -905,9 +905,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: DUMMY_SP, } }; - AttrArgs::Eq(*eq_span, AttrArgsEq::Hir(lit)) + AttrArgs::Eq { eq_span, value: AttrArgsEq::Hir(lit) } } - AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => { + AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { unreachable!("in literal form when lowering mac args eq: {:?}", lit) } } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index d7c531f3760..479677b0a5a 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -648,14 +648,14 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere AttrArgs::Empty => { self.print_path(&item.path, false, 0); } - AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => { + AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => { self.print_path(&item.path, false, 0); self.space(); self.word_space("="); let token_str = self.expr_to_string(expr); self.word(token_str); } - AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => { + AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { self.print_path(&item.path, false, 0); self.space(); self.word_space("="); diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 19c2d466f7c..e5500c8bba1 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -732,7 +732,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { _ => item.to_tokens(), }; let attr_item = attr.unwrap_normal_item(); - if let AttrArgs::Eq(..) = attr_item.args { + if let AttrArgs::Eq { .. } = attr_item.args { self.cx.dcx().emit_err(UnsupportedKeyValue { span }); } let inner_tokens = attr_item.args.inner_tokens(); diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 0ed8d152d2d..37556c064d8 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1376,7 +1376,7 @@ impl<'a> Parser<'a> { AttrArgs::Delimited(args) } else if self.eat(&token::Eq) { let eq_span = self.prev_token.span; - AttrArgs::Eq(eq_span, AttrArgsEq::Ast(self.parse_expr_force_collect()?)) + AttrArgs::Eq { eq_span, value: AttrArgsEq::Ast(self.parse_expr_force_collect()?) } } else { AttrArgs::Empty }) diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index f3174e7dea2..aab3f10bc66 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -43,7 +43,7 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) { } } _ => { - if let AttrArgs::Eq(..) = attr_item.args { + if let AttrArgs::Eq { .. } = attr_item.args { // All key-value attributes are restricted to meta-item syntax. match parse_meta(psess, attr) { Ok(_) => {} @@ -70,7 +70,7 @@ pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Met parse_in(psess, tokens.clone(), "meta list", |p| p.parse_meta_seq_top())?; MetaItemKind::List(nmis) } - AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => { + AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => { if let ast::ExprKind::Lit(token_lit) = expr.kind { let res = ast::MetaItemLit::from_token_lit(token_lit, expr.span); let res = match res { @@ -116,7 +116,9 @@ pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Met return Err(err); } } - AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => MetaItemKind::NameValue(lit.clone()), + AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => { + MetaItemKind::NameValue(lit.clone()) + } }, }) } diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index 02e255d7726..9abf713eb25 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -220,7 +220,7 @@ pub fn attrs_to_doc_fragments<'a>( fn span_for_value(attr: &ast::Attribute) -> Span { if let ast::AttrKind::Normal(normal) = &attr.kind - && let ast::AttrArgs::Eq(_, ast::AttrArgsEq::Hir(meta)) = &normal.item.args + && let ast::AttrArgs::Eq { value: ast::AttrArgsEq::Hir(meta), .. } = &normal.item.args { meta.span.with_ctxt(attr.span.ctxt()) } else { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index 7f42c932fcf..2ba63b6bb49 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -639,8 +639,8 @@ impl<'tcx> OnUnimplementedDirective { let report_span = match &item.args { AttrArgs::Empty => item.path.span, AttrArgs::Delimited(args) => args.dspan.entire(), - AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => eq_span.to(expr.span), - AttrArgs::Eq(span, AttrArgsEq::Hir(expr)) => span.to(expr.span), + AttrArgs::Eq { eq_span, value: AttrArgsEq::Ast(expr) } => eq_span.to(expr.span), + AttrArgs::Eq { eq_span, value: AttrArgsEq::Hir(expr) } => eq_span.to(expr.span), }; if let Some(item_def_id) = item_def_id.as_local() { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 093f216accb..12158483720 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2649,7 +2649,7 @@ fn filter_doc_attr(normal: &mut ast::NormalAttr, is_inline: bool) { }); args.tokens = TokenStream::new(tokens); } - ast::AttrArgs::Empty | ast::AttrArgs::Eq(..) => {} + ast::AttrArgs::Empty | ast::AttrArgs::Eq { .. } => {} } } diff --git a/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs b/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs index fadd5272880..97cffeb098e 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs @@ -9,7 +9,7 @@ use rustc_span::sym; pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) { if let AttrKind::Normal(normal_attr) = &attr.kind { - if let AttrArgs::Eq(_, AttrArgsEq::Ast(_)) = &normal_attr.item.args { + if let AttrArgs::Eq { value: AttrArgsEq::Ast(_), .. } = &normal_attr.item.args { // `#[should_panic = ".."]` found, good return; } diff --git a/src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs b/src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs index 49978d4a655..2182689f985 100644 --- a/src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs +++ b/src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs @@ -12,7 +12,7 @@ pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) { if !attr.span.from_expansion() && let AttrKind::Normal(ref normal) = attr.kind && normal.item.path == sym::doc - && let AttrArgs::Eq(_, AttrArgsEq::Hir(ref meta)) = normal.item.args + && let AttrArgs::Eq { value: AttrArgsEq::Hir(ref meta), .. } = normal.item.args && !attr.span.contains(meta.span) // Since the `include_str` is already expanded at this point, we can only take the // whole attribute snippet and then modify for our suggestion. diff --git a/src/tools/clippy/clippy_lints/src/large_include_file.rs b/src/tools/clippy/clippy_lints/src/large_include_file.rs index 4f22931a4de..b38e362410e 100644 --- a/src/tools/clippy/clippy_lints/src/large_include_file.rs +++ b/src/tools/clippy/clippy_lints/src/large_include_file.rs @@ -96,7 +96,7 @@ impl LateLintPass<'_> for LargeIncludeFile { && let AttrKind::Normal(ref normal) = attr.kind && let Some(doc) = attr.doc_str() && doc.as_str().len() as u64 > self.max_file_size - && let AttrArgs::Eq(_, AttrArgsEq::Hir(ref meta)) = normal.item.args + && let AttrArgs::Eq { value: AttrArgsEq::Hir(ref meta), .. } = normal.item.args && !attr.span.contains(meta.span) // Since the `include_str` is already expanded at this point, we can only take the // whole attribute snippet and then modify for our suggestion. diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index c90f4a6ebfe..620a9b56eb5 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -872,8 +872,8 @@ pub fn eq_attr_args(l: &AttrArgs, r: &AttrArgs) -> bool { match (l, r) { (Empty, Empty) => true, (Delimited(la), Delimited(ra)) => eq_delim_args(la, ra), - (Eq(_, AttrArgsEq::Ast(le)), Eq(_, AttrArgsEq::Ast(re))) => eq_expr(le, re), - (Eq(_, AttrArgsEq::Hir(ll)), Eq(_, AttrArgsEq::Hir(rl))) => ll.kind == rl.kind, + (Eq { value: AttrArgsEq::Ast(le), .. }, Eq{ value: AttrArgsEq::Ast(re), .. }) => eq_expr(le, re), + (Eq { value: AttrArgsEq::Hir(ll), .. }, Eq{ value: AttrArgsEq::Hir(rl), .. }) => ll.kind == rl.kind, _ => false, } } -- cgit 1.4.1-3-g733a5 From e089bead327795727e1a72fd276776f12f186cea Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 2 Dec 2024 13:57:56 +0100 Subject: remove `Ty::is_copy_modulo_regions` --- compiler/rustc_hir_analysis/src/check/check.rs | 2 +- .../rustc_hir_analysis/src/check/intrinsicck.rs | 2 +- compiler/rustc_hir_typeck/src/expr_use_visitor.rs | 2 +- compiler/rustc_lint/src/builtin.rs | 2 +- compiler/rustc_lint/src/context.rs | 4 +++ compiler/rustc_lint/src/drop_forget_useless.rs | 2 +- compiler/rustc_middle/src/ty/util.rs | 33 ++++++++++++---------- .../rustc_mir_build/src/build/expr/as_operand.rs | 2 +- .../src/thir/pattern/check_match.rs | 2 +- compiler/rustc_mir_transform/src/validate.rs | 2 +- compiler/rustc_trait_selection/src/infer.rs | 2 +- compiler/rustc_ty_utils/src/needs_drop.rs | 2 +- .../clippy_lints/src/methods/manual_inspect.rs | 4 +-- src/tools/clippy/clippy_lints/src/question_mark.rs | 2 +- src/tools/clippy/clippy_utils/src/ty.rs | 2 +- 15 files changed, 36 insertions(+), 29 deletions(-) (limited to 'src/tools') diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index e1f4ccca97e..022a6d457ec 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -103,7 +103,7 @@ fn allowed_union_or_unsafe_field<'tcx>( // Fallback case: allow `ManuallyDrop` and things that are `Copy`, // also no need to report an error if the type is unresolved. ty.ty_adt_def().is_some_and(|adt_def| adt_def.is_manually_drop()) - || ty.is_copy_modulo_regions(tcx, typing_env) + || tcx.type_is_copy_modulo_regions(typing_env, ty) || ty.references_error() } }; diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index b96469f503c..df4da03f0f5 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -178,7 +178,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { // Check that the type implements Copy. The only case where this can // possibly fail is for SIMD types which don't #[derive(Copy)]. - if !ty.is_copy_modulo_regions(self.tcx, self.typing_env) { + if !self.tcx.type_is_copy_modulo_regions(self.typing_env, ty) { let msg = "arguments for inline assembly must be copyable"; self.tcx .dcx() diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 2a00530c434..774d00edea0 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -228,7 +228,7 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) { } fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool { - ty.is_copy_modulo_regions(self.0.tcx, self.0.typing_env()) + self.0.type_is_copy_modulo_regions(ty) } fn body_owner_def_id(&self) -> LocalDefId { diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index e130cfc1d73..ec085198922 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -586,7 +586,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { return; } } - if ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()) { + if cx.type_is_copy_modulo_regions(ty) { return; } if type_implements_negative_copy_modulo_regions(cx.tcx, ty, cx.typing_env()) { diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 7248b192763..44c7888a530 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -710,6 +710,10 @@ impl<'tcx> LateContext<'tcx> { TypingEnv { typing_mode: self.typing_mode(), param_env: self.param_env } } + pub fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool { + self.tcx.type_is_copy_modulo_regions(self.typing_env(), ty) + } + /// Gets the type-checking results for the current body, /// or `None` if outside a body. pub fn maybe_typeck_results(&self) -> Option<&'tcx ty::TypeckResults<'tcx>> { diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs index 8fe86738658..ce23892508b 100644 --- a/compiler/rustc_lint/src/drop_forget_useless.rs +++ b/compiler/rustc_lint/src/drop_forget_useless.rs @@ -144,7 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { && let Some(fn_name) = cx.tcx.get_diagnostic_name(def_id) { let arg_ty = cx.typeck_results().expr_ty(arg); - let is_copy = arg_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()); + let is_copy = cx.type_is_copy_modulo_regions(arg_ty); let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr); let let_underscore_ignore_sugg = || { if let Some((_, node)) = cx.tcx.hir().parent_iter(expr.hir_id).nth(0) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 797ac9685b1..57054bd1a0b 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -172,6 +172,24 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// Checks whether `ty: Copy` holds while ignoring region constraints. + /// + /// This impacts whether values of `ty` are *moved* or *copied* + /// when referenced. This means that we may generate MIR which + /// does copies even when the type actually doesn't satisfy the + /// full requirements for the `Copy` trait (cc #29149) -- this + /// winds up being reported as an error during NLL borrow check. + /// + /// This function should not be used if there is an `InferCtxt` available. + /// Use `InferCtxt::type_is_copy_modulo_regions` instead. + pub fn type_is_copy_modulo_regions( + self, + typing_env: ty::TypingEnv<'tcx>, + ty: Ty<'tcx>, + ) -> bool { + ty.is_trivially_pure_clone_copy() || self.is_copy_raw(typing_env.as_query_input(ty)) + } + /// Returns the deeply last field of nested structures, or the same type if /// not a structure at all. Corresponds to the only possible unsized field, /// and its type can be used to determine unsizing strategy. @@ -1174,21 +1192,6 @@ impl<'tcx> Ty<'tcx> { .map(|(min, _)| ty::Const::from_bits(tcx, min, typing_env, self)) } - /// Checks whether values of this type `T` are *moved* or *copied* - /// when referenced -- this amounts to a check for whether `T: - /// Copy`, but note that we **don't** consider lifetimes when - /// doing this check. This means that we may generate MIR which - /// does copies even when the type actually doesn't satisfy the - /// full requirements for the `Copy` trait (cc #29149) -- this - /// winds up being reported as an error during NLL borrow check. - pub fn is_copy_modulo_regions( - self, - tcx: TyCtxt<'tcx>, - typing_env: ty::TypingEnv<'tcx>, - ) -> bool { - self.is_trivially_pure_clone_copy() || tcx.is_copy_raw(typing_env.as_query_input(self)) - } - /// Checks whether values of this type `T` have a size known at /// compile time (i.e., whether `T: Sized`). Lifetimes are ignored /// for the purposes of this check, so it can be an diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs index 0cab853196b..777ff9e68f0 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs @@ -176,7 +176,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let ty = expr.ty; if !ty.is_sized(tcx, this.typing_env()) { // !sized means !copy, so this is an unsized move - assert!(!ty.is_copy_modulo_regions(tcx, this.typing_env())); + assert!(!tcx.type_is_copy_modulo_regions(this.typing_env(), ty)); // As described above, detect the case where we are passing a value of unsized // type, and that value is coming from the deref of a box. diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index e55cd35e243..a13b00e1921 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -780,7 +780,7 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat: return; }; - let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.typing_env); + let is_binding_by_move = |ty: Ty<'tcx>| !cx.tcx.type_is_copy_modulo_regions(cx.typing_env, ty); let sess = cx.tcx.sess; diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 51e5c49cea1..f67d9a77825 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -624,7 +624,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if let Operand::Copy(place) = operand { let ty = place.ty(&self.body.local_decls, self.tcx).ty; - if !ty.is_copy_modulo_regions(self.tcx, self.typing_env) { + if !self.tcx.type_is_copy_modulo_regions(self.typing_env, ty) { self.fail(location, format!("`Operand::Copy` with non-`Copy` type {ty}")); } } diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 43244eb5dcb..ee708564a80 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -35,7 +35,7 @@ impl<'tcx> InferCtxt<'tcx> { // FIXME(#132279): This should be removed as it causes us to incorrectly // handle opaques in their defining scope. if !(param_env, ty).has_infer() { - return ty.is_copy_modulo_regions(self.tcx, self.typing_env(param_env)); + return self.tcx.type_is_copy_modulo_regions(self.typing_env(param_env), ty); } let copy_def_id = self.tcx.require_lang_item(LangItem::Copy, None); diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index d85da7d355e..1c85eb2a861 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -202,7 +202,7 @@ where } } - _ if component.is_copy_modulo_regions(tcx, self.typing_env) => {} + _ if tcx.type_is_copy_modulo_regions(self.typing_env, component) => {} ty::Closure(_, args) => { for upvar in args.as_closure().upvar_tys() { diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs index 865a42b65c6..20e4d233525 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs @@ -148,7 +148,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name: _ => {}, } } - requires_copy |= !ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()); + requires_copy |= !cx.type_is_copy_modulo_regions(ty); break; } }, @@ -158,7 +158,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name: } if can_lint - && (!requires_copy || arg_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env())) + && (!requires_copy || cx.type_is_copy_modulo_regions(arg_ty)) // This case could be handled, but a fair bit of care would need to be taken. && (!requires_deref || arg_ty.is_freeze(cx.tcx, cx.typing_env())) { diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index 4b96858d8f6..77abe7151f0 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -251,7 +251,7 @@ fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Ex { let mut applicability = Applicability::MachineApplicable; let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability); - let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()) + let by_ref = !cx.type_is_copy_modulo_regions(caller_ty) && !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)); let sugg = if let Some(else_inner) = r#else { if eq_expr_value(cx, caller, peel_blocks(else_inner)) { diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 39c9d234a1a..260d1b801e3 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -38,7 +38,7 @@ pub use type_certainty::expr_type_is_certain; /// Checks if the given type implements copy. pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()) + cx.type_is_copy_modulo_regions(ty) } /// This checks whether a given type is known to implement Debug. -- cgit 1.4.1-3-g733a5 From 59e3e8934e3e50ddb9b9a9ffaa523cbab2260598 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 4 Nov 2024 19:29:02 +0000 Subject: Gate async fn trait bound modifier on async_trait_bounds --- compiler/rustc_ast_passes/src/feature_gate.rs | 5 +++++ compiler/rustc_feature/src/unstable.rs | 2 ++ compiler/rustc_parse/src/parser/ty.rs | 4 ++-- compiler/rustc_span/src/symbol.rs | 1 + .../miri/tests/pass/async-closure-captures.rs | 2 +- src/tools/miri/tests/pass/async-closure-drop.rs | 2 +- tests/codegen/async-closure-debug.rs | 2 +- tests/coverage/async_closure.cov-map | 8 ++++---- tests/coverage/async_closure.coverage | 2 +- tests/coverage/async_closure.rs | 2 +- tests/crashes/124020.rs | 4 ++-- tests/ui/async-await/async-fn/dyn-pos.rs | 2 +- tests/ui/async-await/async-fn/dyn-pos.stderr | 4 ++-- tests/ui/async-await/async-fn/edition-2015.rs | 4 ++-- tests/ui/async-await/async-fn/edition-2015.stderr | 12 +++++------ ...mbe-async-trait-bound-theoretical-regression.rs | 4 ++-- ...async-trait-bound-theoretical-regression.stderr | 12 +++++------ tests/ui/async-await/async-fn/not-a-trait.rs | 2 +- tests/ui/async-await/async-fn/sugar.rs | 2 +- .../async-await/async-fn/trait-bounds-in-macro.rs | 2 +- .../async-fn/trait-bounds-in-macro.stderr | 6 +++--- tests/ui/async-await/async-fn/wrong-trait.rs | 2 +- .../feature-gate-async-trait-bounds.rs | 7 +++++++ .../feature-gate-async-trait-bounds.stderr | 24 ++++++++++++++++++++++ .../precise-capturing/bound-modifiers.rs | 2 +- .../precise-capturing/bound-modifiers.stderr | 6 +++--- tests/ui/parser/bad-recover-kw-after-impl.rs | 2 +- tests/ui/parser/bad-recover-kw-after-impl.stderr | 6 +++--- 28 files changed, 86 insertions(+), 47 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-async-trait-bounds.rs create mode 100644 tests/ui/feature-gates/feature-gate-async-trait-bounds.stderr (limited to 'src/tools') diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 8cdc7133cc0..0c925cd8fa2 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -516,6 +516,11 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { "async closures are unstable", "to use an async block, remove the `||`: `async {`" ); + gate_all!( + async_trait_bounds, + "`async` trait bounds are unstable", + "use the desugared name of the async trait, such as `AsyncFn`" + ); gate_all!(async_for_loop, "`for await` loops are experimental"); gate_all!( closure_lifetime_binder, diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index ec908762da7..cb6bc03f9e2 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -394,6 +394,8 @@ declare_features! ( (unstable, async_fn_track_caller, "1.73.0", Some(110011)), /// Allows `for await` loops. (unstable, async_for_loop, "1.77.0", Some(118898)), + /// Allows `async` trait bound modifier. + (unstable, async_trait_bounds, "CURRENT_RUSTC_VERSION", Some(62290)), /// Allows using C-variadics. (unstable, c_variadic, "1.34.0", Some(44930)), /// Allows the use of `#[cfg()]`. diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 505586e74f1..1340558d968 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -940,7 +940,7 @@ impl<'a> Parser<'a> { let asyncness = if self.token.uninterpolated_span().at_least_rust_2018() && self.eat_keyword(kw::Async) { - self.psess.gated_spans.gate(sym::async_closure, self.prev_token.span); + self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span); BoundAsyncness::Async(self.prev_token.span) } else if self.may_recover() && self.token.uninterpolated_span().is_rust_2015() @@ -951,7 +951,7 @@ impl<'a> Parser<'a> { span: self.prev_token.span, help: HelpUseLatestEdition::new(), }); - self.psess.gated_spans.gate(sym::async_closure, self.prev_token.span); + self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span); BoundAsyncness::Async(self.prev_token.span) } else { BoundAsyncness::Normal diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e94c0a5ea6e..b2ca86bf486 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -468,6 +468,7 @@ symbols! { async_for_loop, async_iterator, async_iterator_poll_next, + async_trait_bounds, atomic, atomic_mod, atomics, diff --git a/src/tools/miri/tests/pass/async-closure-captures.rs b/src/tools/miri/tests/pass/async-closure-captures.rs index cac26bfe146..423ef7a5cf7 100644 --- a/src/tools/miri/tests/pass/async-closure-captures.rs +++ b/src/tools/miri/tests/pass/async-closure-captures.rs @@ -1,6 +1,6 @@ // Same as rustc's `tests/ui/async-await/async-closures/captures.rs`, keep in sync -#![feature(async_closure, noop_waker)] +#![feature(async_closure, noop_waker, async_trait_bounds)] use std::future::Future; use std::pin::pin; diff --git a/src/tools/miri/tests/pass/async-closure-drop.rs b/src/tools/miri/tests/pass/async-closure-drop.rs index 9b2fc2948bf..264da5a9518 100644 --- a/src/tools/miri/tests/pass/async-closure-drop.rs +++ b/src/tools/miri/tests/pass/async-closure-drop.rs @@ -1,4 +1,4 @@ -#![feature(async_closure, noop_waker, async_fn_traits)] +#![feature(async_closure, noop_waker, async_trait_bounds)] use std::future::Future; use std::pin::pin; diff --git a/tests/codegen/async-closure-debug.rs b/tests/codegen/async-closure-debug.rs index 9cb1e623295..644df169a36 100644 --- a/tests/codegen/async-closure-debug.rs +++ b/tests/codegen/async-closure-debug.rs @@ -9,7 +9,7 @@ #![feature(async_closure)] -fn async_closure_test(upvar: &str) -> impl async Fn() + '_ { +fn async_closure_test(upvar: &str) -> impl AsyncFn() + '_ { async move || { let hello = String::from("hello"); println!("{hello}, {upvar}"); diff --git a/tests/coverage/async_closure.cov-map b/tests/coverage/async_closure.cov-map index 4d00f0d9b33..9ff29af8e8e 100644 --- a/tests/coverage/async_closure.cov-map +++ b/tests/coverage/async_closure.cov-map @@ -1,19 +1,19 @@ Function name: async_closure::call_once:: -Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 00, 2c] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 00, 2b] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 44) +- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 43) Highest counter ID seen: c0 Function name: async_closure::call_once::::{closure#0} -Raw bytes (14): 0x[01, 01, 00, 02, 01, 07, 2c, 01, 0e, 05, 02, 01, 00, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 07, 2b, 01, 0e, 05, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 7, 44) to (start + 1, 14) +- Code(Counter(0)) at (prev + 7, 43) to (start + 1, 14) - Code(Counter(1)) at (prev + 2, 1) to (start + 0, 2) Highest counter ID seen: c1 diff --git a/tests/coverage/async_closure.coverage b/tests/coverage/async_closure.coverage index fd6edf7c29e..75da1a01fc1 100644 --- a/tests/coverage/async_closure.coverage +++ b/tests/coverage/async_closure.coverage @@ -4,7 +4,7 @@ LL| |//@ aux-build: executor.rs LL| |extern crate executor; LL| | - LL| 1|async fn call_once(f: impl async FnOnce()) { + LL| 1|async fn call_once(f: impl AsyncFnOnce()) { LL| 1| f().await; LL| 1|} LL| | diff --git a/tests/coverage/async_closure.rs b/tests/coverage/async_closure.rs index c076d03eef4..cbac592d957 100644 --- a/tests/coverage/async_closure.rs +++ b/tests/coverage/async_closure.rs @@ -4,7 +4,7 @@ //@ aux-build: executor.rs extern crate executor; -async fn call_once(f: impl async FnOnce()) { +async fn call_once(f: impl AsyncFnOnce()) { f().await; } diff --git a/tests/crashes/124020.rs b/tests/crashes/124020.rs index f461f32f59d..1b875497465 100644 --- a/tests/crashes/124020.rs +++ b/tests/crashes/124020.rs @@ -1,7 +1,7 @@ //@ known-bug: #124020 //@ compile-flags: -Zpolymorphize=on --edition=2018 --crate-type=lib -#![feature(async_closure, noop_waker, async_fn_traits)] +#![feature(async_closure, noop_waker, async_trait_bounds)] use std::future::Future; use std::pin::pin; @@ -19,7 +19,7 @@ pub fn block_on(fut: impl Future) -> T { } } -async fn call_once(f: impl async FnOnce(DropMe)) { +async fn call_once(f: impl AsyncFnOnce(DropMe)) { f(DropMe("world")).await; } diff --git a/tests/ui/async-await/async-fn/dyn-pos.rs b/tests/ui/async-await/async-fn/dyn-pos.rs index a16b7c26f0d..129ea282936 100644 --- a/tests/ui/async-await/async-fn/dyn-pos.rs +++ b/tests/ui/async-await/async-fn/dyn-pos.rs @@ -2,7 +2,7 @@ #![feature(async_closure)] -fn foo(x: &dyn async Fn()) {} +fn foo(x: &dyn AsyncFn()) {} //~^ ERROR the trait `AsyncFnMut` cannot be made into an object fn main() {} diff --git a/tests/ui/async-await/async-fn/dyn-pos.stderr b/tests/ui/async-await/async-fn/dyn-pos.stderr index a9abfc5e5c4..aaa8eb2634d 100644 --- a/tests/ui/async-await/async-fn/dyn-pos.stderr +++ b/tests/ui/async-await/async-fn/dyn-pos.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `AsyncFnMut` cannot be made into an object --> $DIR/dyn-pos.rs:5:16 | -LL | fn foo(x: &dyn async Fn()) {} - | ^^^^^^^^^^ `AsyncFnMut` cannot be made into an object +LL | fn foo(x: &dyn AsyncFn()) {} + | ^^^^^^^^^ `AsyncFnMut` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL diff --git a/tests/ui/async-await/async-fn/edition-2015.rs b/tests/ui/async-await/async-fn/edition-2015.rs index e38179758f6..7fc62a8dd93 100644 --- a/tests/ui/async-await/async-fn/edition-2015.rs +++ b/tests/ui/async-await/async-fn/edition-2015.rs @@ -1,8 +1,8 @@ fn foo(x: impl async Fn()) -> impl async Fn() { x } //~^ ERROR `async` trait bounds are only allowed in Rust 2018 or later //~| ERROR `async` trait bounds are only allowed in Rust 2018 or later -//~| ERROR async closures are unstable -//~| ERROR async closures are unstable +//~| ERROR `async` trait bounds are unstable +//~| ERROR `async` trait bounds are unstable //~| ERROR use of unstable library feature `async_closure` //~| ERROR use of unstable library feature `async_closure` diff --git a/tests/ui/async-await/async-fn/edition-2015.stderr b/tests/ui/async-await/async-fn/edition-2015.stderr index 9fbceafd75d..96fb4c9e979 100644 --- a/tests/ui/async-await/async-fn/edition-2015.stderr +++ b/tests/ui/async-await/async-fn/edition-2015.stderr @@ -16,27 +16,27 @@ LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } = help: pass `--edition 2024` to `rustc` = note: for more on editions, read https://doc.rust-lang.org/edition-guide -error[E0658]: async closures are unstable +error[E0658]: `async` trait bounds are unstable --> $DIR/edition-2015.rs:1:16 | LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } | ^^^^^ | = note: see issue #62290 for more information - = help: add `#![feature(async_closure)]` to the crate attributes to enable + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: to use an async block, remove the `||`: `async {` + = help: use the desugared name of the async trait, such as `AsyncFn` -error[E0658]: async closures are unstable +error[E0658]: `async` trait bounds are unstable --> $DIR/edition-2015.rs:1:36 | LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } | ^^^^^ | = note: see issue #62290 for more information - = help: add `#![feature(async_closure)]` to the crate attributes to enable + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: to use an async block, remove the `||`: `async {` + = help: use the desugared name of the async trait, such as `AsyncFn` error[E0658]: use of unstable library feature `async_closure` --> $DIR/edition-2015.rs:1:42 diff --git a/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.rs b/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.rs index abc429772fd..ea67831b68e 100644 --- a/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.rs +++ b/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.rs @@ -13,9 +13,9 @@ macro_rules! demo { } demo! { impl async Trait } -//~^ ERROR async closures are unstable +//~^ ERROR `async` trait bounds are unstable demo! { dyn async Trait } -//~^ ERROR async closures are unstable +//~^ ERROR `async` trait bounds are unstable fn main() {} diff --git a/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.stderr b/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.stderr index 13b8e72b49d..a463944d113 100644 --- a/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.stderr +++ b/tests/ui/async-await/async-fn/mbe-async-trait-bound-theoretical-regression.stderr @@ -20,27 +20,27 @@ LL | demo! { dyn async Trait } | = note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0658]: async closures are unstable +error[E0658]: `async` trait bounds are unstable --> $DIR/mbe-async-trait-bound-theoretical-regression.rs:15:14 | LL | demo! { impl async Trait } | ^^^^^ | = note: see issue #62290 for more information - = help: add `#![feature(async_closure)]` to the crate attributes to enable + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: to use an async block, remove the `||`: `async {` + = help: use the desugared name of the async trait, such as `AsyncFn` -error[E0658]: async closures are unstable +error[E0658]: `async` trait bounds are unstable --> $DIR/mbe-async-trait-bound-theoretical-regression.rs:18:13 | LL | demo! { dyn async Trait } | ^^^^^ | = note: see issue #62290 for more information - = help: add `#![feature(async_closure)]` to the crate attributes to enable + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: to use an async block, remove the `||`: `async {` + = help: use the desugared name of the async trait, such as `AsyncFn` error: aborting due to 4 previous errors diff --git a/tests/ui/async-await/async-fn/not-a-trait.rs b/tests/ui/async-await/async-fn/not-a-trait.rs index 0d22cbd2c07..5cf23f2456a 100644 --- a/tests/ui/async-await/async-fn/not-a-trait.rs +++ b/tests/ui/async-await/async-fn/not-a-trait.rs @@ -1,6 +1,6 @@ //@ edition:2018 -#![feature(async_closure)] +#![feature(async_trait_bounds)] struct S; diff --git a/tests/ui/async-await/async-fn/sugar.rs b/tests/ui/async-await/async-fn/sugar.rs index 29b6abc814a..0225b666ac5 100644 --- a/tests/ui/async-await/async-fn/sugar.rs +++ b/tests/ui/async-await/async-fn/sugar.rs @@ -1,7 +1,7 @@ //@ edition: 2021 //@ check-pass -#![feature(async_closure)] +#![feature(async_closure, async_trait_bounds)] async fn foo() {} diff --git a/tests/ui/async-await/async-fn/trait-bounds-in-macro.rs b/tests/ui/async-await/async-fn/trait-bounds-in-macro.rs index 329a1528e8b..654883966f4 100644 --- a/tests/ui/async-await/async-fn/trait-bounds-in-macro.rs +++ b/tests/ui/async-await/async-fn/trait-bounds-in-macro.rs @@ -6,7 +6,7 @@ macro_rules! x { x! { async fn foo() -> impl async Fn() { } - //~^ ERROR async closures are unstable + //~^ ERROR `async` trait bounds are unstable } fn main() {} diff --git a/tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr b/tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr index f68c09737db..259e13cd1fe 100644 --- a/tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr +++ b/tests/ui/async-await/async-fn/trait-bounds-in-macro.stderr @@ -1,13 +1,13 @@ -error[E0658]: async closures are unstable +error[E0658]: `async` trait bounds are unstable --> $DIR/trait-bounds-in-macro.rs:8:28 | LL | async fn foo() -> impl async Fn() { } | ^^^^^ | = note: see issue #62290 for more information - = help: add `#![feature(async_closure)]` to the crate attributes to enable + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: to use an async block, remove the `||`: `async {` + = help: use the desugared name of the async trait, such as `AsyncFn` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/async-fn/wrong-trait.rs b/tests/ui/async-await/async-fn/wrong-trait.rs index e6fb0b46712..38d6bb1d01a 100644 --- a/tests/ui/async-await/async-fn/wrong-trait.rs +++ b/tests/ui/async-await/async-fn/wrong-trait.rs @@ -1,6 +1,6 @@ //@ edition:2018 -#![feature(async_closure)] +#![feature(async_trait_bounds)] trait Foo {} diff --git a/tests/ui/feature-gates/feature-gate-async-trait-bounds.rs b/tests/ui/feature-gates/feature-gate-async-trait-bounds.rs new file mode 100644 index 00000000000..db5d7aa06d2 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-async-trait-bounds.rs @@ -0,0 +1,7 @@ +//@ edition: 2021 + +fn test(_: impl async Fn()) {} +//~^ ERROR `async` trait bounds are unstable +//~| ERROR use of unstable library feature `async_closure` + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-async-trait-bounds.stderr b/tests/ui/feature-gates/feature-gate-async-trait-bounds.stderr new file mode 100644 index 00000000000..abc7e37c45f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-async-trait-bounds.stderr @@ -0,0 +1,24 @@ +error[E0658]: `async` trait bounds are unstable + --> $DIR/feature-gate-async-trait-bounds.rs:3:17 + | +LL | fn test(_: impl async Fn()) {} + | ^^^^^ + | + = note: see issue #62290 for more information + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: use the desugared name of the async trait, such as `AsyncFn` + +error[E0658]: use of unstable library feature `async_closure` + --> $DIR/feature-gate-async-trait-bounds.rs:3:23 + | +LL | fn test(_: impl async Fn()) {} + | ^^^^ + | + = note: see issue #62290 for more information + = help: add `#![feature(async_closure)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs b/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs index 46121308fa0..cac5ae177d2 100644 --- a/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs +++ b/tests/ui/impl-trait/precise-capturing/bound-modifiers.rs @@ -7,7 +7,7 @@ fn polarity() -> impl Sized + ?use<> {} fn asyncness() -> impl Sized + async use<> {} //~^ ERROR expected identifier, found keyword `use` //~| ERROR cannot find trait `r#use` in this scope -//~| ERROR async closures are unstable +//~| ERROR `async` trait bounds are unstable fn constness() -> impl Sized + const use<> {} //~^ ERROR expected identifier, found keyword `use` diff --git a/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr b/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr index 16e7470debf..d4b5b47b41b 100644 --- a/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr +++ b/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr @@ -46,16 +46,16 @@ error[E0405]: cannot find trait `r#use` in this scope LL | fn binder() -> impl Sized + for<'a> use<> {} | ^^^ not found in this scope -error[E0658]: async closures are unstable +error[E0658]: `async` trait bounds are unstable --> $DIR/bound-modifiers.rs:7:32 | LL | fn asyncness() -> impl Sized + async use<> {} | ^^^^^ | = note: see issue #62290 for more information - = help: add `#![feature(async_closure)]` to the crate attributes to enable + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: to use an async block, remove the `||`: `async {` + = help: use the desugared name of the async trait, such as `AsyncFn` error[E0658]: const trait impls are experimental --> $DIR/bound-modifiers.rs:12:32 diff --git a/tests/ui/parser/bad-recover-kw-after-impl.rs b/tests/ui/parser/bad-recover-kw-after-impl.rs index 15c0b377c8a..964d32c55bc 100644 --- a/tests/ui/parser/bad-recover-kw-after-impl.rs +++ b/tests/ui/parser/bad-recover-kw-after-impl.rs @@ -12,6 +12,6 @@ macro_rules! impl_primitive { impl_primitive!(impl async); //~^ ERROR expected identifier, found `` -//~| ERROR async closures are unstable +//~| ERROR `async` trait bounds are unstable fn main() {} diff --git a/tests/ui/parser/bad-recover-kw-after-impl.stderr b/tests/ui/parser/bad-recover-kw-after-impl.stderr index f617cf65498..7a8979db165 100644 --- a/tests/ui/parser/bad-recover-kw-after-impl.stderr +++ b/tests/ui/parser/bad-recover-kw-after-impl.stderr @@ -7,16 +7,16 @@ LL | ($ty:ty) => { LL | impl_primitive!(impl async); | ^^^^^ expected identifier -error[E0658]: async closures are unstable +error[E0658]: `async` trait bounds are unstable --> $DIR/bad-recover-kw-after-impl.rs:13:22 | LL | impl_primitive!(impl async); | ^^^^^ | = note: see issue #62290 for more information - = help: add `#![feature(async_closure)]` to the crate attributes to enable + = help: add `#![feature(async_trait_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: to use an async block, remove the `||`: `async {` + = help: use the desugared name of the async trait, such as `AsyncFn` error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From 5e34c2e43c9110ac91579cb1b6d44ebdba0b5712 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 10 Dec 2023 18:16:53 +0100 Subject: Drop uplifted `clippy::fn_address_comparisons` --- .../clippy/clippy_lints/src/declared_lints.rs | 1 - .../clippy/clippy_lints/src/deprecated_lints.rs | 2 + src/tools/clippy/clippy_lints/src/lib.rs | 2 - .../clippy/clippy_lints/src/unnamed_address.rs | 60 --------- .../clippy/tests/ui/fn_address_comparisons.rs | 23 ---- .../clippy/tests/ui/fn_address_comparisons.stderr | 17 --- src/tools/clippy/tests/ui/rename.fixed | 2 + src/tools/clippy/tests/ui/rename.rs | 2 + src/tools/clippy/tests/ui/rename.stderr | 140 +++++++++++---------- 9 files changed, 79 insertions(+), 170 deletions(-) delete mode 100644 src/tools/clippy/clippy_lints/src/unnamed_address.rs delete mode 100644 src/tools/clippy/tests/ui/fn_address_comparisons.rs delete mode 100644 src/tools/clippy/tests/ui/fn_address_comparisons.stderr (limited to 'src/tools') diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index c4a0c8f1865..022ed180ed8 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs @@ -744,7 +744,6 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::unit_types::LET_UNIT_VALUE_INFO, crate::unit_types::UNIT_ARG_INFO, crate::unit_types::UNIT_CMP_INFO, - crate::unnamed_address::FN_ADDRESS_COMPARISONS_INFO, crate::unnecessary_box_returns::UNNECESSARY_BOX_RETURNS_INFO, crate::unnecessary_literal_bound::UNNECESSARY_LITERAL_BOUND_INFO, crate::unnecessary_map_on_constructor::UNNECESSARY_MAP_ON_CONSTRUCTOR_INFO, diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs index 77dbe9b78a1..3ea792d8b83 100644 --- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs +++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs @@ -74,6 +74,8 @@ declare_with_version! { RENAMED(RENAMED_VERSION): &[(&str, &str)] = &[ #[clippy::version = "1.53.0"] ("clippy::filter_map", "clippy::manual_filter_map"), #[clippy::version = ""] + ("clippy::fn_address_comparisons", "unpredictable_function_pointer_comparisons"), + #[clippy::version = ""] ("clippy::identity_conversion", "clippy::useless_conversion"), #[clippy::version = "pre 1.29.0"] ("clippy::if_let_redundant_pattern_matching", "clippy::redundant_pattern_matching"), diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index c9064df25ac..e80cca6e7db 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -363,7 +363,6 @@ mod uninhabited_references; mod uninit_vec; mod unit_return_expecting_ord; mod unit_types; -mod unnamed_address; mod unnecessary_box_returns; mod unnecessary_literal_bound; mod unnecessary_map_on_constructor; @@ -786,7 +785,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_early_pass(|| Box::new(option_env_unwrap::OptionEnvUnwrap)); store.register_late_pass(move |_| Box::new(wildcard_imports::WildcardImports::new(conf))); store.register_late_pass(|_| Box::::default()); - store.register_late_pass(|_| Box::new(unnamed_address::UnnamedAddress)); store.register_late_pass(|_| Box::>::default()); store.register_late_pass(|_| Box::new(option_if_let_else::OptionIfLetElse)); store.register_late_pass(|_| Box::new(future_not_send::FutureNotSend)); diff --git a/src/tools/clippy/clippy_lints/src/unnamed_address.rs b/src/tools/clippy/clippy_lints/src/unnamed_address.rs deleted file mode 100644 index cd2dacc9f09..00000000000 --- a/src/tools/clippy/clippy_lints/src/unnamed_address.rs +++ /dev/null @@ -1,60 +0,0 @@ -use clippy_utils::diagnostics::span_lint; -use rustc_hir::{BinOpKind, Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty; -use rustc_session::declare_lint_pass; - -declare_clippy_lint! { - /// ### What it does - /// Checks for comparisons with an address of a function item. - /// - /// ### Why is this bad? - /// Function item address is not guaranteed to be unique and could vary - /// between different code generation units. Furthermore different function items could have - /// the same address after being merged together. - /// - /// ### Example - /// ```no_run - /// type F = fn(); - /// fn a() {} - /// let f: F = a; - /// if f == a { - /// // ... - /// } - /// ``` - #[clippy::version = "1.44.0"] - pub FN_ADDRESS_COMPARISONS, - correctness, - "comparison with an address of a function item" -} - -declare_lint_pass!(UnnamedAddress => [FN_ADDRESS_COMPARISONS]); - -impl LateLintPass<'_> for UnnamedAddress { - fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { - fn is_comparison(binop: BinOpKind) -> bool { - matches!( - binop, - BinOpKind::Eq | BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ne | BinOpKind::Ge | BinOpKind::Gt - ) - } - - fn is_fn_def(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - matches!(cx.typeck_results().expr_ty(expr).kind(), ty::FnDef(..)) - } - - if let ExprKind::Binary(binop, left, right) = expr.kind - && is_comparison(binop.node) - && cx.typeck_results().expr_ty_adjusted(left).is_fn_ptr() - && cx.typeck_results().expr_ty_adjusted(right).is_fn_ptr() - && (is_fn_def(cx, left) || is_fn_def(cx, right)) - { - span_lint( - cx, - FN_ADDRESS_COMPARISONS, - expr.span, - "comparing with a non-unique address of a function item", - ); - } - } -} diff --git a/src/tools/clippy/tests/ui/fn_address_comparisons.rs b/src/tools/clippy/tests/ui/fn_address_comparisons.rs deleted file mode 100644 index 35535bd4fdd..00000000000 --- a/src/tools/clippy/tests/ui/fn_address_comparisons.rs +++ /dev/null @@ -1,23 +0,0 @@ -use std::fmt::Debug; -use std::ptr; -use std::rc::Rc; -use std::sync::Arc; - -fn a() {} - -#[warn(clippy::fn_address_comparisons)] -fn main() { - type F = fn(); - let f: F = a; - let g: F = f; - - // These should fail: - let _ = f == a; - //~^ ERROR: comparing with a non-unique address of a function item - //~| NOTE: `-D clippy::fn-address-comparisons` implied by `-D warnings` - let _ = f != a; - //~^ ERROR: comparing with a non-unique address of a function item - - // These should be fine: - let _ = f == g; -} diff --git a/src/tools/clippy/tests/ui/fn_address_comparisons.stderr b/src/tools/clippy/tests/ui/fn_address_comparisons.stderr deleted file mode 100644 index e6de7e35807..00000000000 --- a/src/tools/clippy/tests/ui/fn_address_comparisons.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error: comparing with a non-unique address of a function item - --> tests/ui/fn_address_comparisons.rs:15:13 - | -LL | let _ = f == a; - | ^^^^^^ - | - = note: `-D clippy::fn-address-comparisons` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::fn_address_comparisons)]` - -error: comparing with a non-unique address of a function item - --> tests/ui/fn_address_comparisons.rs:18:13 - | -LL | let _ = f != a; - | ^^^^^^ - -error: aborting due to 2 previous errors - diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed index 0d6e07aa546..47149622ef7 100644 --- a/src/tools/clippy/tests/ui/rename.fixed +++ b/src/tools/clippy/tests/ui/rename.fixed @@ -59,6 +59,7 @@ #![allow(unknown_lints)] #![allow(unused_labels)] #![allow(ambiguous_wide_pointer_comparisons)] +#![allow(unpredictable_function_pointer_comparisons)] #![allow(clippy::reversed_empty_ranges)] #![warn(clippy::almost_complete_range)] //~ ERROR: lint `clippy::almost_complete_letter_range` #![warn(clippy::disallowed_names)] //~ ERROR: lint `clippy::blacklisted_name` @@ -74,6 +75,7 @@ #![warn(clippy::mixed_read_write_in_expression)] //~ ERROR: lint `clippy::eval_order_dependence` #![warn(clippy::manual_find_map)] //~ ERROR: lint `clippy::find_map` #![warn(clippy::manual_filter_map)] //~ ERROR: lint `clippy::filter_map` +#![warn(unpredictable_function_pointer_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons` #![warn(clippy::useless_conversion)] //~ ERROR: lint `clippy::identity_conversion` #![warn(clippy::redundant_pattern_matching)] //~ ERROR: lint `clippy::if_let_redundant_pattern_matching` #![warn(clippy::match_result_ok)] //~ ERROR: lint `clippy::if_let_some_result` diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs index 2ac59718786..7a78a5d280d 100644 --- a/src/tools/clippy/tests/ui/rename.rs +++ b/src/tools/clippy/tests/ui/rename.rs @@ -59,6 +59,7 @@ #![allow(unknown_lints)] #![allow(unused_labels)] #![allow(ambiguous_wide_pointer_comparisons)] +#![allow(unpredictable_function_pointer_comparisons)] #![allow(clippy::reversed_empty_ranges)] #![warn(clippy::almost_complete_letter_range)] //~ ERROR: lint `clippy::almost_complete_letter_range` #![warn(clippy::blacklisted_name)] //~ ERROR: lint `clippy::blacklisted_name` @@ -74,6 +75,7 @@ #![warn(clippy::eval_order_dependence)] //~ ERROR: lint `clippy::eval_order_dependence` #![warn(clippy::find_map)] //~ ERROR: lint `clippy::find_map` #![warn(clippy::filter_map)] //~ ERROR: lint `clippy::filter_map` +#![warn(clippy::fn_address_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons` #![warn(clippy::identity_conversion)] //~ ERROR: lint `clippy::identity_conversion` #![warn(clippy::if_let_redundant_pattern_matching)] //~ ERROR: lint `clippy::if_let_redundant_pattern_matching` #![warn(clippy::if_let_some_result)] //~ ERROR: lint `clippy::if_let_some_result` diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr index a5ae727b7ee..dc24bc16d0e 100644 --- a/src/tools/clippy/tests/ui/rename.stderr +++ b/src/tools/clippy/tests/ui/rename.stderr @@ -1,5 +1,5 @@ error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range` - --> tests/ui/rename.rs:63:9 + --> tests/ui/rename.rs:64:9 | LL | #![warn(clippy::almost_complete_letter_range)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range` @@ -8,394 +8,400 @@ LL | #![warn(clippy::almost_complete_letter_range)] = help: to override `-D warnings` add `#[allow(renamed_and_removed_lints)]` error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names` - --> tests/ui/rename.rs:64:9 + --> tests/ui/rename.rs:65:9 | LL | #![warn(clippy::blacklisted_name)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names` error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_conditions` - --> tests/ui/rename.rs:65:9 + --> tests/ui/rename.rs:66:9 | LL | #![warn(clippy::block_in_if_condition_expr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions` error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_conditions` - --> tests/ui/rename.rs:66:9 + --> tests/ui/rename.rs:67:9 | LL | #![warn(clippy::block_in_if_condition_stmt)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions` error: lint `clippy::blocks_in_if_conditions` has been renamed to `clippy::blocks_in_conditions` - --> tests/ui/rename.rs:67:9 + --> tests/ui/rename.rs:68:9 | LL | #![warn(clippy::blocks_in_if_conditions)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions` error: lint `clippy::box_vec` has been renamed to `clippy::box_collection` - --> tests/ui/rename.rs:68:9 + --> tests/ui/rename.rs:69:9 | LL | #![warn(clippy::box_vec)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection` error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes` - --> tests/ui/rename.rs:69:9 + --> tests/ui/rename.rs:70:9 | LL | #![warn(clippy::const_static_lifetime)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes` error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity` - --> tests/ui/rename.rs:70:9 + --> tests/ui/rename.rs:71:9 | LL | #![warn(clippy::cyclomatic_complexity)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity` error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq` - --> tests/ui/rename.rs:71:9 + --> tests/ui/rename.rs:72:9 | LL | #![warn(clippy::derive_hash_xor_eq)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq` error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods` - --> tests/ui/rename.rs:72:9 + --> tests/ui/rename.rs:73:9 | LL | #![warn(clippy::disallowed_method)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods` error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types` - --> tests/ui/rename.rs:73:9 + --> tests/ui/rename.rs:74:9 | LL | #![warn(clippy::disallowed_type)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types` error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression` - --> tests/ui/rename.rs:74:9 + --> tests/ui/rename.rs:75:9 | LL | #![warn(clippy::eval_order_dependence)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression` error: lint `clippy::find_map` has been renamed to `clippy::manual_find_map` - --> tests/ui/rename.rs:75:9 + --> tests/ui/rename.rs:76:9 | LL | #![warn(clippy::find_map)] | ^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_find_map` error: lint `clippy::filter_map` has been renamed to `clippy::manual_filter_map` - --> tests/ui/rename.rs:76:9 + --> tests/ui/rename.rs:77:9 | LL | #![warn(clippy::filter_map)] | ^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_filter_map` +error: lint `clippy::fn_address_comparisons` has been renamed to `unpredictable_function_pointer_comparisons` + --> tests/ui/rename.rs:78:9 + | +LL | #![warn(clippy::fn_address_comparisons)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unpredictable_function_pointer_comparisons` + error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion` - --> tests/ui/rename.rs:77:9 + --> tests/ui/rename.rs:79:9 | LL | #![warn(clippy::identity_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion` error: lint `clippy::if_let_redundant_pattern_matching` has been renamed to `clippy::redundant_pattern_matching` - --> tests/ui/rename.rs:78:9 + --> tests/ui/rename.rs:80:9 | LL | #![warn(clippy::if_let_redundant_pattern_matching)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_pattern_matching` error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok` - --> tests/ui/rename.rs:79:9 + --> tests/ui/rename.rs:81:9 | LL | #![warn(clippy::if_let_some_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok` error: lint `clippy::incorrect_clone_impl_on_copy_type` has been renamed to `clippy::non_canonical_clone_impl` - --> tests/ui/rename.rs:80:9 + --> tests/ui/rename.rs:82:9 | LL | #![warn(clippy::incorrect_clone_impl_on_copy_type)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_clone_impl` error: lint `clippy::incorrect_partial_ord_impl_on_ord_type` has been renamed to `clippy::non_canonical_partial_ord_impl` - --> tests/ui/rename.rs:81:9 + --> tests/ui/rename.rs:83:9 | LL | #![warn(clippy::incorrect_partial_ord_impl_on_ord_type)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_partial_ord_impl` error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects` - --> tests/ui/rename.rs:82:9 + --> tests/ui/rename.rs:84:9 | LL | #![warn(clippy::integer_arithmetic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects` error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr` - --> tests/ui/rename.rs:83:9 + --> tests/ui/rename.rs:85:9 | LL | #![warn(clippy::logic_bug)] | ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr` error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default` - --> tests/ui/rename.rs:84:9 + --> tests/ui/rename.rs:86:9 | LL | #![warn(clippy::new_without_default_derive)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default` error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map` - --> tests/ui/rename.rs:85:9 + --> tests/ui/rename.rs:87:9 | LL | #![warn(clippy::option_and_then_some)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map` error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used` - --> tests/ui/rename.rs:86:9 + --> tests/ui/rename.rs:88:9 | LL | #![warn(clippy::option_expect_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or` - --> tests/ui/rename.rs:87:9 + --> tests/ui/rename.rs:89:9 | LL | #![warn(clippy::option_map_unwrap_or)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` - --> tests/ui/rename.rs:88:9 + --> tests/ui/rename.rs:90:9 | LL | #![warn(clippy::option_map_unwrap_or_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used` - --> tests/ui/rename.rs:89:9 + --> tests/ui/rename.rs:91:9 | LL | #![warn(clippy::option_unwrap_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` error: lint `clippy::overflow_check_conditional` has been renamed to `clippy::panicking_overflow_checks` - --> tests/ui/rename.rs:90:9 + --> tests/ui/rename.rs:92:9 | LL | #![warn(clippy::overflow_check_conditional)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::panicking_overflow_checks` error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow` - --> tests/ui/rename.rs:91:9 + --> tests/ui/rename.rs:93:9 | LL | #![warn(clippy::ref_in_deref)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow` error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used` - --> tests/ui/rename.rs:92:9 + --> tests/ui/rename.rs:94:9 | LL | #![warn(clippy::result_expect_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` - --> tests/ui/rename.rs:93:9 + --> tests/ui/rename.rs:95:9 | LL | #![warn(clippy::result_map_unwrap_or_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used` - --> tests/ui/rename.rs:94:9 + --> tests/ui/rename.rs:96:9 | LL | #![warn(clippy::result_unwrap_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str` - --> tests/ui/rename.rs:95:9 + --> tests/ui/rename.rs:97:9 | LL | #![warn(clippy::single_char_push_str)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str` error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions` - --> tests/ui/rename.rs:96:9 + --> tests/ui/rename.rs:98:9 | LL | #![warn(clippy::stutter)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions` error: lint `clippy::thread_local_initializer_can_be_made_const` has been renamed to `clippy::missing_const_for_thread_local` - --> tests/ui/rename.rs:97:9 + --> tests/ui/rename.rs:99:9 | LL | #![warn(clippy::thread_local_initializer_can_be_made_const)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::missing_const_for_thread_local` error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl` - --> tests/ui/rename.rs:98:9 + --> tests/ui/rename.rs:100:9 | LL | #![warn(clippy::to_string_in_display)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl` error: lint `clippy::unwrap_or_else_default` has been renamed to `clippy::unwrap_or_default` - --> tests/ui/rename.rs:99:9 + --> tests/ui/rename.rs:101:9 | LL | #![warn(clippy::unwrap_or_else_default)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_or_default` error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters` - --> tests/ui/rename.rs:100:9 + --> tests/ui/rename.rs:102:9 | LL | #![warn(clippy::zero_width_space)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters` error: lint `clippy::cast_ref_to_mut` has been renamed to `invalid_reference_casting` - --> tests/ui/rename.rs:101:9 + --> tests/ui/rename.rs:103:9 | LL | #![warn(clippy::cast_ref_to_mut)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_reference_casting` error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op` - --> tests/ui/rename.rs:102:9 + --> tests/ui/rename.rs:104:9 | LL | #![warn(clippy::clone_double_ref)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op` error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons` - --> tests/ui/rename.rs:103:9 + --> tests/ui/rename.rs:105:9 | LL | #![warn(clippy::cmp_nan)] | ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons` error: lint `clippy::drop_bounds` has been renamed to `drop_bounds` - --> tests/ui/rename.rs:104:9 + --> tests/ui/rename.rs:106:9 | LL | #![warn(clippy::drop_bounds)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds` error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types` - --> tests/ui/rename.rs:105:9 + --> tests/ui/rename.rs:107:9 | LL | #![warn(clippy::drop_copy)] | ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types` error: lint `clippy::drop_ref` has been renamed to `dropping_references` - --> tests/ui/rename.rs:106:9 + --> tests/ui/rename.rs:108:9 | LL | #![warn(clippy::drop_ref)] | ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references` error: lint `clippy::fn_null_check` has been renamed to `useless_ptr_null_checks` - --> tests/ui/rename.rs:107:9 + --> tests/ui/rename.rs:109:9 | LL | #![warn(clippy::fn_null_check)] | ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `useless_ptr_null_checks` error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles` - --> tests/ui/rename.rs:108:9 + --> tests/ui/rename.rs:110:9 | LL | #![warn(clippy::for_loop_over_option)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles` - --> tests/ui/rename.rs:109:9 + --> tests/ui/rename.rs:111:9 | LL | #![warn(clippy::for_loop_over_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles` - --> tests/ui/rename.rs:110:9 + --> tests/ui/rename.rs:112:9 | LL | #![warn(clippy::for_loops_over_fallibles)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types` - --> tests/ui/rename.rs:111:9 + --> tests/ui/rename.rs:113:9 | LL | #![warn(clippy::forget_copy)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types` error: lint `clippy::forget_ref` has been renamed to `forgetting_references` - --> tests/ui/rename.rs:112:9 + --> tests/ui/rename.rs:114:9 | LL | #![warn(clippy::forget_ref)] | ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references` error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter` - --> tests/ui/rename.rs:113:9 + --> tests/ui/rename.rs:115:9 | LL | #![warn(clippy::into_iter_on_array)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter` error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering` - --> tests/ui/rename.rs:114:9 + --> tests/ui/rename.rs:116:9 | LL | #![warn(clippy::invalid_atomic_ordering)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering` error: lint `clippy::invalid_ref` has been renamed to `invalid_value` - --> tests/ui/rename.rs:115:9 + --> tests/ui/rename.rs:117:9 | LL | #![warn(clippy::invalid_ref)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value` error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked` - --> tests/ui/rename.rs:116:9 + --> tests/ui/rename.rs:118:9 | LL | #![warn(clippy::invalid_utf8_in_unchecked)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked` error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop` - --> tests/ui/rename.rs:117:9 + --> tests/ui/rename.rs:119:9 | LL | #![warn(clippy::let_underscore_drop)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop` error: lint `clippy::maybe_misused_cfg` has been renamed to `unexpected_cfgs` - --> tests/ui/rename.rs:118:9 + --> tests/ui/rename.rs:120:9 | LL | #![warn(clippy::maybe_misused_cfg)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs` error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums` - --> tests/ui/rename.rs:119:9 + --> tests/ui/rename.rs:121:9 | LL | #![warn(clippy::mem_discriminant_non_enum)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums` error: lint `clippy::mismatched_target_os` has been renamed to `unexpected_cfgs` - --> tests/ui/rename.rs:120:9 + --> tests/ui/rename.rs:122:9 | LL | #![warn(clippy::mismatched_target_os)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs` error: lint `clippy::panic_params` has been renamed to `non_fmt_panics` - --> tests/ui/rename.rs:121:9 + --> tests/ui/rename.rs:123:9 | LL | #![warn(clippy::panic_params)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics` error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally` - --> tests/ui/rename.rs:122:9 + --> tests/ui/rename.rs:124:9 | LL | #![warn(clippy::positional_named_format_parameters)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally` error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `dangling_pointers_from_temporaries` - --> tests/ui/rename.rs:123:9 + --> tests/ui/rename.rs:125:9 | LL | #![warn(clippy::temporary_cstring_as_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `dangling_pointers_from_temporaries` error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops` - --> tests/ui/rename.rs:124:9 + --> tests/ui/rename.rs:126:9 | LL | #![warn(clippy::undropped_manually_drops)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops` error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints` - --> tests/ui/rename.rs:125:9 + --> tests/ui/rename.rs:127:9 | LL | #![warn(clippy::unknown_clippy_lints)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints` error: lint `clippy::unused_label` has been renamed to `unused_labels` - --> tests/ui/rename.rs:126:9 + --> tests/ui/rename.rs:128:9 | LL | #![warn(clippy::unused_label)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` error: lint `clippy::vtable_address_comparisons` has been renamed to `ambiguous_wide_pointer_comparisons` - --> tests/ui/rename.rs:127:9 + --> tests/ui/rename.rs:129:9 | LL | #![warn(clippy::vtable_address_comparisons)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `ambiguous_wide_pointer_comparisons` error: lint `clippy::reverse_range_loop` has been renamed to `clippy::reversed_empty_ranges` - --> tests/ui/rename.rs:128:9 + --> tests/ui/rename.rs:130:9 | LL | #![warn(clippy::reverse_range_loop)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::reversed_empty_ranges` -error: aborting due to 66 previous errors +error: aborting due to 67 previous errors -- cgit 1.4.1-3-g733a5 From 8ce63576bddc95e99b54ebf8ec9da6f52a647ad2 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 10 Dec 2023 15:51:06 +0100 Subject: Allow fn pointers comparisons lint in UI tests --- src/tools/miri/tests/pass/function_pointers.rs | 2 ++ src/tools/miri/tests/pass/issues/issue-91636.rs | 2 ++ tests/ui/binop/binary-op-on-fn-ptr-eq.rs | 3 +++ tests/ui/box/unit/unique-ffi-symbols.rs | 3 +++ tests/ui/consts/const-extern-function.rs | 2 ++ tests/ui/cross-crate/const-cross-crate-extern.rs | 2 ++ tests/ui/extern/extern-compare-with-return-type.rs | 1 + tests/ui/extern/extern-take-value.rs | 2 ++ tests/ui/function-pointer/function-pointer-comparison-issue-54685.rs | 2 ++ tests/ui/issues/issue-54696.rs | 2 ++ tests/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs | 2 ++ 11 files changed, 23 insertions(+) (limited to 'src/tools') diff --git a/src/tools/miri/tests/pass/function_pointers.rs b/src/tools/miri/tests/pass/function_pointers.rs index a5c4bc5e0d9..7145be334a1 100644 --- a/src/tools/miri/tests/pass/function_pointers.rs +++ b/src/tools/miri/tests/pass/function_pointers.rs @@ -1,3 +1,5 @@ +#![allow(unpredictable_function_pointer_comparisons)] + use std::mem; trait Answer { diff --git a/src/tools/miri/tests/pass/issues/issue-91636.rs b/src/tools/miri/tests/pass/issues/issue-91636.rs index 00370165812..d0cadcd2c70 100644 --- a/src/tools/miri/tests/pass/issues/issue-91636.rs +++ b/src/tools/miri/tests/pass/issues/issue-91636.rs @@ -1,3 +1,5 @@ +#![allow(unpredictable_function_pointer_comparisons)] + type BuiltIn = for<'a> fn(&str); struct Function { diff --git a/tests/ui/binop/binary-op-on-fn-ptr-eq.rs b/tests/ui/binop/binary-op-on-fn-ptr-eq.rs index a5ec63587f9..47b79f3855f 100644 --- a/tests/ui/binop/binary-op-on-fn-ptr-eq.rs +++ b/tests/ui/binop/binary-op-on-fn-ptr-eq.rs @@ -1,6 +1,9 @@ //@ run-pass // Tests equality between supertype and subtype of a function // See the issue #91636 + +#![allow(unpredictable_function_pointer_comparisons)] + fn foo(_a: &str) {} fn main() { diff --git a/tests/ui/box/unit/unique-ffi-symbols.rs b/tests/ui/box/unit/unique-ffi-symbols.rs index 65a9a32b2bb..75877f8397e 100644 --- a/tests/ui/box/unit/unique-ffi-symbols.rs +++ b/tests/ui/box/unit/unique-ffi-symbols.rs @@ -1,6 +1,9 @@ //@ run-pass // We used to have a __rust_abi shim that resulted in duplicated symbols // whenever the item path wasn't enough to disambiguate between them. + +#![allow(unpredictable_function_pointer_comparisons)] + fn main() { let a = { extern "C" fn good() -> i32 { return 0; } diff --git a/tests/ui/consts/const-extern-function.rs b/tests/ui/consts/const-extern-function.rs index acc438189cb..7629d63266a 100644 --- a/tests/ui/consts/const-extern-function.rs +++ b/tests/ui/consts/const-extern-function.rs @@ -1,5 +1,7 @@ //@ run-pass + #![allow(non_upper_case_globals)] +#![allow(unpredictable_function_pointer_comparisons)] extern "C" fn foopy() {} diff --git a/tests/ui/cross-crate/const-cross-crate-extern.rs b/tests/ui/cross-crate/const-cross-crate-extern.rs index 8d48a6a5206..0ec8753c30f 100644 --- a/tests/ui/cross-crate/const-cross-crate-extern.rs +++ b/tests/ui/cross-crate/const-cross-crate-extern.rs @@ -1,6 +1,8 @@ //@ run-pass //@ aux-build:cci_const.rs + #![allow(non_upper_case_globals)] +#![allow(unpredictable_function_pointer_comparisons)] extern crate cci_const; use cci_const::bar; diff --git a/tests/ui/extern/extern-compare-with-return-type.rs b/tests/ui/extern/extern-compare-with-return-type.rs index 316e8b2fc73..7d1027d5e77 100644 --- a/tests/ui/extern/extern-compare-with-return-type.rs +++ b/tests/ui/extern/extern-compare-with-return-type.rs @@ -2,6 +2,7 @@ // Tests that we can compare various kinds of extern fn signatures. #![allow(non_camel_case_types)] +#![allow(unpredictable_function_pointer_comparisons)] // `dbg!()` differentiates these functions to ensure they won't be merged. extern "C" fn voidret1() { dbg!() } diff --git a/tests/ui/extern/extern-take-value.rs b/tests/ui/extern/extern-take-value.rs index 56ed3328614..f3df82b2610 100644 --- a/tests/ui/extern/extern-take-value.rs +++ b/tests/ui/extern/extern-take-value.rs @@ -1,6 +1,8 @@ //@ run-pass //@ aux-build:extern-take-value.rs +#![allow(unpredictable_function_pointer_comparisons)] + extern crate extern_take_value; pub fn main() { diff --git a/tests/ui/function-pointer/function-pointer-comparison-issue-54685.rs b/tests/ui/function-pointer/function-pointer-comparison-issue-54685.rs index 2e1c863e0f4..3ec958f2ebf 100644 --- a/tests/ui/function-pointer/function-pointer-comparison-issue-54685.rs +++ b/tests/ui/function-pointer/function-pointer-comparison-issue-54685.rs @@ -1,6 +1,8 @@ //@ compile-flags: -C opt-level=3 //@ run-pass +#![allow(unpredictable_function_pointer_comparisons)] + fn foo(_i: i32) -> i32 { 1 } diff --git a/tests/ui/issues/issue-54696.rs b/tests/ui/issues/issue-54696.rs index 75b1824f0b3..63ffbe42bcc 100644 --- a/tests/ui/issues/issue-54696.rs +++ b/tests/ui/issues/issue-54696.rs @@ -1,5 +1,7 @@ //@ run-pass +#![allow(unpredictable_function_pointer_comparisons)] + fn main() { // We shouldn't promote this let _ = &(main as fn() == main as fn()); diff --git a/tests/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs b/tests/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs index 44b7fae351c..45d519739eb 100644 --- a/tests/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs +++ b/tests/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs @@ -1,6 +1,8 @@ //@ check-pass //@ compile-flags: -Zvalidate-mir +#![allow(unpredictable_function_pointer_comparisons)] + fn foo(_a: &str) {} fn main() { -- cgit 1.4.1-3-g733a5 From eadea7764ee49e11165ed041e529cbe79707a31c Mon Sep 17 00:00:00 2001 From: Kornel Date: Sat, 30 Nov 2024 20:32:00 +0000 Subject: Use c"lit" for CStrings without unwrap --- compiler/rustc_codegen_llvm/src/back/lto.rs | 2 +- compiler/rustc_codegen_llvm/src/back/write.rs | 2 +- .../rustc_error_codes/src/error_codes/E0060.md | 13 +++------ library/alloc/src/ffi/c_str.rs | 32 ++++++++++------------ library/alloc/src/ffi/c_str/tests.rs | 2 +- library/alloc/src/rc/tests.rs | 4 +-- library/alloc/src/sync/tests.rs | 4 +-- .../std/src/sys/pal/unix/process/process_common.rs | 2 +- .../miri/tests/pass-dep/libc/libc-fs-symlink.rs | 3 +- .../tests/pass-dep/libc/libc-fs-with-isolation.rs | 4 +-- src/tools/miri/tests/pass-dep/libc/libc-mem.rs | 10 +++---- .../crates/profile/src/memory_usage.rs | 4 +-- tests/run-make/libtest-thread-limit/rmake.rs | 2 +- tests/ui/process/env-funky-keys.rs | 4 +-- 14 files changed, 38 insertions(+), 50 deletions(-) (limited to 'src/tools') diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 48beb9be2b2..f6d2ec24da6 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -148,7 +148,7 @@ fn prepare_lto( // __llvm_profile_counter_bias is pulled in at link time by an undefined reference to // __llvm_profile_runtime, therefore we won't know until link time if this symbol // should have default visibility. - symbols_below_threshold.push(CString::new("__llvm_profile_counter_bias").unwrap()); + symbols_below_threshold.push(c"__llvm_profile_counter_bias".to_owned()); Ok((symbols_below_threshold, upstream_modules)) } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 2744795d998..bde6668929c 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -509,7 +509,7 @@ fn get_pgo_sample_use_path(config: &ModuleConfig) -> Option { } fn get_instr_profile_output_path(config: &ModuleConfig) -> Option { - config.instrument_coverage.then(|| CString::new("default_%m_%p.profraw").unwrap()) + config.instrument_coverage.then(|| c"default_%m_%p.profraw".to_owned()) } pub(crate) unsafe fn llvm_optimize( diff --git a/compiler/rustc_error_codes/src/error_codes/E0060.md b/compiler/rustc_error_codes/src/error_codes/E0060.md index 54b10c886cc..a6831c881e3 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0060.md +++ b/compiler/rustc_error_codes/src/error_codes/E0060.md @@ -15,7 +15,7 @@ unsafe { printf(); } // error! Using this declaration, it must be called with at least one argument, so simply calling `printf()` is invalid. But the following uses are allowed: -``` +```rust,edition2021 # use std::os::raw::{c_char, c_int}; # #[cfg_attr(all(windows, target_env = "msvc"), # link(name = "legacy_stdio_definitions", @@ -23,16 +23,11 @@ simply calling `printf()` is invalid. But the following uses are allowed: # extern "C" { fn printf(_: *const c_char, ...) -> c_int; } # fn main() { unsafe { - use std::ffi::CString; - - let fmt = CString::new("test\n").unwrap(); - printf(fmt.as_ptr()); + printf(c"test\n".as_ptr()); - let fmt = CString::new("number = %d\n").unwrap(); - printf(fmt.as_ptr(), 3); + printf(c"number = %d\n".as_ptr(), 3); - let fmt = CString::new("%d, %d\n").unwrap(); - printf(fmt.as_ptr(), 10, 5); + printf(c"%d, %d\n".as_ptr(), 10, 5); } # } ``` diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index c739832bc78..9c074383a5e 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -384,7 +384,7 @@ impl CString { /// fn some_extern_function(s: *mut c_char); /// } /// - /// let c_string = CString::new("Hello!").expect("CString::new failed"); + /// let c_string = CString::from(c"Hello!"); /// let raw = c_string.into_raw(); /// unsafe { /// some_extern_function(raw); @@ -429,7 +429,7 @@ impl CString { /// ``` /// use std::ffi::CString; /// - /// let c_string = CString::new("foo").expect("CString::new failed"); + /// let c_string = CString::from(c"foo"); /// /// let ptr = c_string.into_raw(); /// @@ -487,7 +487,7 @@ impl CString { /// ``` /// use std::ffi::CString; /// - /// let c_string = CString::new("foo").expect("CString::new failed"); + /// let c_string = CString::from(c"foo"); /// let bytes = c_string.into_bytes(); /// assert_eq!(bytes, vec![b'f', b'o', b'o']); /// ``` @@ -508,7 +508,7 @@ impl CString { /// ``` /// use std::ffi::CString; /// - /// let c_string = CString::new("foo").expect("CString::new failed"); + /// let c_string = CString::from(c"foo"); /// let bytes = c_string.into_bytes_with_nul(); /// assert_eq!(bytes, vec![b'f', b'o', b'o', b'\0']); /// ``` @@ -530,7 +530,7 @@ impl CString { /// ``` /// use std::ffi::CString; /// - /// let c_string = CString::new("foo").expect("CString::new failed"); + /// let c_string = CString::from(c"foo"); /// let bytes = c_string.as_bytes(); /// assert_eq!(bytes, &[b'f', b'o', b'o']); /// ``` @@ -550,7 +550,7 @@ impl CString { /// ``` /// use std::ffi::CString; /// - /// let c_string = CString::new("foo").expect("CString::new failed"); + /// let c_string = CString::from(c"foo"); /// let bytes = c_string.as_bytes_with_nul(); /// assert_eq!(bytes, &[b'f', b'o', b'o', b'\0']); /// ``` @@ -568,7 +568,7 @@ impl CString { /// ``` /// use std::ffi::{CString, CStr}; /// - /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed"); + /// let c_string = CString::from(c"foo"); /// let cstr = c_string.as_c_str(); /// assert_eq!(cstr, /// CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed")); @@ -586,12 +586,9 @@ impl CString { /// # Examples /// /// ``` - /// use std::ffi::{CString, CStr}; - /// - /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed"); + /// let c_string = c"foo".to_owned(); /// let boxed = c_string.into_boxed_c_str(); - /// assert_eq!(&*boxed, - /// CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed")); + /// assert_eq!(boxed.to_bytes_with_nul(), b"foo\0"); /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "into_boxed_c_str", since = "1.20.0")] @@ -658,7 +655,7 @@ impl CString { /// assert_eq!( /// CString::from_vec_with_nul(b"abc\0".to_vec()) /// .expect("CString::from_vec_with_nul failed"), - /// CString::new(b"abc".to_vec()).expect("CString::new failed") + /// c"abc".to_owned() /// ); /// ``` /// @@ -1168,11 +1165,12 @@ impl CStr { /// # Examples /// /// ``` - /// use std::ffi::CString; + /// use std::ffi::{CStr, CString}; /// - /// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed"); - /// let boxed = c_string.into_boxed_c_str(); - /// assert_eq!(boxed.into_c_string(), CString::new("foo").expect("CString::new failed")); + /// let boxed: Box = Box::from(c"foo"); + /// let c_string: CString = c"foo".to_owned(); + /// + /// assert_eq!(boxed.into_c_string(), c_string); /// ``` #[rustc_allow_incoherent_impl] #[must_use = "`self` will be dropped if the result is not used"] diff --git a/library/alloc/src/ffi/c_str/tests.rs b/library/alloc/src/ffi/c_str/tests.rs index 8b7172b3f20..d6b797347c2 100644 --- a/library/alloc/src/ffi/c_str/tests.rs +++ b/library/alloc/src/ffi/c_str/tests.rs @@ -159,7 +159,7 @@ fn boxed_default() { #[test] fn test_c_str_clone_into() { - let mut c_string = CString::new("lorem").unwrap(); + let mut c_string = c"lorem".to_owned(); let c_ptr = c_string.as_ptr(); let c_str = CStr::from_bytes_with_nul(b"ipsum\0").unwrap(); c_str.clone_into(&mut c_string); diff --git a/library/alloc/src/rc/tests.rs b/library/alloc/src/rc/tests.rs index 333e1bde31c..2210a7c24c0 100644 --- a/library/alloc/src/rc/tests.rs +++ b/library/alloc/src/rc/tests.rs @@ -349,9 +349,9 @@ fn test_unsized() { #[test] fn test_maybe_thin_unsized() { // If/when custom thin DSTs exist, this test should be updated to use one - use std::ffi::{CStr, CString}; + use std::ffi::CStr; - let x: Rc = Rc::from(CString::new("swordfish").unwrap().into_boxed_c_str()); + let x: Rc = Rc::from(c"swordfish"); assert_eq!(format!("{x:?}"), "\"swordfish\""); let y: Weak = Rc::downgrade(&x); drop(x); diff --git a/library/alloc/src/sync/tests.rs b/library/alloc/src/sync/tests.rs index 3f66c889923..de5816fda97 100644 --- a/library/alloc/src/sync/tests.rs +++ b/library/alloc/src/sync/tests.rs @@ -412,9 +412,9 @@ fn test_unsized() { #[test] fn test_maybe_thin_unsized() { // If/when custom thin DSTs exist, this test should be updated to use one - use std::ffi::{CStr, CString}; + use std::ffi::CStr; - let x: Arc = Arc::from(CString::new("swordfish").unwrap().into_boxed_c_str()); + let x: Arc = Arc::from(c"swordfish"); assert_eq!(format!("{x:?}"), "\"swordfish\""); let y: Weak = Arc::downgrade(&x); drop(x); diff --git a/library/std/src/sys/pal/unix/process/process_common.rs b/library/std/src/sys/pal/unix/process/process_common.rs index 13290fed762..342818ac911 100644 --- a/library/std/src/sys/pal/unix/process/process_common.rs +++ b/library/std/src/sys/pal/unix/process/process_common.rs @@ -393,7 +393,7 @@ impl Command { fn os2c(s: &OsStr, saw_nul: &mut bool) -> CString { CString::new(s.as_bytes()).unwrap_or_else(|_e| { *saw_nul = true; - CString::new("").unwrap() + c"".to_owned() }) } diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs index a35c92636ce..4b49e105562 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs @@ -47,9 +47,8 @@ fn test_readlink() { assert_eq!(res, small_buf.len() as isize); // Test that we report a proper error for a missing path. - let bad_path = CString::new("MIRI_MISSING_FILE_NAME").unwrap(); let res = unsafe { - libc::readlink(bad_path.as_ptr(), small_buf.as_mut_ptr().cast(), small_buf.len()) + libc::readlink(c"MIRI_MISSING_FILE_NAME".as_ptr(), small_buf.as_mut_ptr().cast(), small_buf.len()) }; assert_eq!(res, -1); assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound); diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs index ab3fd6733ff..cffcf4a867f 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs @@ -2,7 +2,6 @@ //@compile-flags: -Zmiri-isolation-error=warn-nobacktrace //@normalize-stderr-test: "(stat(x)?)" -> "$$STAT" -use std::ffi::CString; use std::fs; use std::io::{Error, ErrorKind}; @@ -13,10 +12,9 @@ fn main() { } // test `readlink` - let symlink_c_str = CString::new("foo.txt").unwrap(); let mut buf = vec![0; "foo_link.txt".len() + 1]; unsafe { - assert_eq!(libc::readlink(symlink_c_str.as_ptr(), buf.as_mut_ptr(), buf.len()), -1); + assert_eq!(libc::readlink(c"foo.txt".as_ptr(), buf.as_mut_ptr(), buf.len()), -1); assert_eq!(Error::last_os_error().raw_os_error(), Some(libc::EACCES)); } diff --git a/src/tools/miri/tests/pass-dep/libc/libc-mem.rs b/src/tools/miri/tests/pass-dep/libc/libc-mem.rs index 10be78798a6..727533a9de6 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-mem.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-mem.rs @@ -55,12 +55,12 @@ fn test_memcpy() { } fn test_strcpy() { - use std::ffi::{CStr, CString}; + use std::ffi::CStr; // case: src_size equals dest_size unsafe { - let src = CString::new("rust").unwrap(); - let size = src.as_bytes_with_nul().len(); + let src = c"rust"; + let size = src.to_bytes_with_nul().len(); let dest = libc::malloc(size); libc::strcpy(dest as *mut libc::c_char, src.as_ptr()); assert_eq!(CStr::from_ptr(dest as *const libc::c_char), src.as_ref()); @@ -69,8 +69,8 @@ fn test_strcpy() { // case: src_size is less than dest_size unsafe { - let src = CString::new("rust").unwrap(); - let size = src.as_bytes_with_nul().len(); + let src = c"rust"; + let size = src.to_bytes_with_nul().len(); let dest = libc::malloc(size + 1); libc::strcpy(dest as *mut libc::c_char, src.as_ptr()); assert_eq!(CStr::from_ptr(dest as *const libc::c_char), src.as_ref()); diff --git a/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs b/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs index 660afff3dca..006748ddb08 100644 --- a/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs +++ b/src/tools/rust-analyzer/crates/profile/src/memory_usage.rs @@ -62,15 +62,13 @@ fn memusage_linux() -> MemoryUsage { // mallinfo2 is very recent, so its presence needs to be detected at runtime. // Both are abysmally slow. - use std::ffi::CStr; use std::sync::atomic::{AtomicUsize, Ordering}; static MALLINFO2: AtomicUsize = AtomicUsize::new(1); let mut mallinfo2 = MALLINFO2.load(Ordering::Relaxed); if mallinfo2 == 1 { - let cstr = CStr::from_bytes_with_nul(b"mallinfo2\0").unwrap(); - mallinfo2 = unsafe { libc::dlsym(libc::RTLD_DEFAULT, cstr.as_ptr()) } as usize; + mallinfo2 = unsafe { libc::dlsym(libc::RTLD_DEFAULT, c"mallinfo2".as_ptr()) } as usize; // NB: races don't matter here, since they'll always store the same value MALLINFO2.store(mallinfo2, Ordering::Relaxed); } diff --git a/tests/run-make/libtest-thread-limit/rmake.rs b/tests/run-make/libtest-thread-limit/rmake.rs index 5decd802b34..fe14d2c046c 100644 --- a/tests/run-make/libtest-thread-limit/rmake.rs +++ b/tests/run-make/libtest-thread-limit/rmake.rs @@ -38,7 +38,7 @@ fn main() { // If the process ID is 0, this is the child process responsible for running the test // program. if pid == 0 { - let test = CString::new("test").unwrap(); + let test = c"test"; // The argv array should be terminated with a NULL pointer. let argv = [test.as_ptr(), std::ptr::null()]; // rlim_cur is soft limit, rlim_max is hard limit. diff --git a/tests/ui/process/env-funky-keys.rs b/tests/ui/process/env-funky-keys.rs index 314ccaea015..a4a71c94020 100644 --- a/tests/ui/process/env-funky-keys.rs +++ b/tests/ui/process/env-funky-keys.rs @@ -1,4 +1,5 @@ //@ run-pass +//@ edition: 2021 // Ignore this test on Android, because it segfaults there. //@ ignore-android @@ -32,10 +33,9 @@ fn main() { .unwrap() .as_os_str() .as_bytes()).unwrap(); - let new_env_var = CString::new("FOOBAR").unwrap(); let filename: *const c_char = current_exe.as_ptr(); let argv: &[*const c_char] = &[filename, filename, ptr::null()]; - let envp: &[*const c_char] = &[new_env_var.as_ptr(), ptr::null()]; + let envp: &[*const c_char] = &[c"FOOBAR".as_ptr(), ptr::null()]; unsafe { execve(filename, &argv[0], &envp[0]); } -- cgit 1.4.1-3-g733a5 From cea0582dbdd231c46884ca917de3e32b75b6287a Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 2 Dec 2024 21:15:38 -0800 Subject: miri: Adapt for `breakpoint` becoming safe --- src/tools/miri/tests/fail/breakpoint.rs | 4 +--- src/tools/miri/tests/fail/breakpoint.stderr | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'src/tools') diff --git a/src/tools/miri/tests/fail/breakpoint.rs b/src/tools/miri/tests/fail/breakpoint.rs index 2dd87ea6083..42943d58191 100644 --- a/src/tools/miri/tests/fail/breakpoint.rs +++ b/src/tools/miri/tests/fail/breakpoint.rs @@ -1,7 +1,5 @@ #![feature(core_intrinsics)] fn main() { - unsafe { - core::intrinsics::breakpoint() //~ ERROR: trace/breakpoint trap - }; + core::intrinsics::breakpoint(); //~ ERROR: trace/breakpoint trap } diff --git a/src/tools/miri/tests/fail/breakpoint.stderr b/src/tools/miri/tests/fail/breakpoint.stderr index ca98e81f1f4..f203cb0c15f 100644 --- a/src/tools/miri/tests/fail/breakpoint.stderr +++ b/src/tools/miri/tests/fail/breakpoint.stderr @@ -1,8 +1,8 @@ error: abnormal termination: trace/breakpoint trap --> tests/fail/breakpoint.rs:LL:CC | -LL | core::intrinsics::breakpoint() - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trace/breakpoint trap +LL | core::intrinsics::breakpoint(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trace/breakpoint trap | = note: BACKTRACE: = note: inside `main` at tests/fail/breakpoint.rs:LL:CC -- cgit 1.4.1-3-g733a5 From a69fe84ec841c20d229711d6861c5d889851e7f5 Mon Sep 17 00:00:00 2001 From: Rémy Rakic Date: Mon, 2 Dec 2024 16:16:41 +0000 Subject: switch jemalloc-sys back to tikv-jemalloc-sys, and update to 0.6.0 --- Cargo.lock | 24 ++++++++++++------------ compiler/rustc/Cargo.toml | 6 +++--- compiler/rustc/src/main.rs | 2 ++ src/librustdoc/lib.rs | 2 +- src/tools/miri/Cargo.toml | 4 ++-- src/tools/miri/src/bin/miri.rs | 2 ++ src/tools/tidy/src/deps.rs | 2 +- 7 files changed, 23 insertions(+), 19 deletions(-) (limited to 'src/tools') diff --git a/Cargo.lock b/Cargo.lock index 8ccf05cc5b8..a96e0685858 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1877,16 +1877,6 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" -[[package]] -name = "jemalloc-sys" -version = "0.5.4+5.3.0-patched" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac6c1946e1cea1788cbfde01c993b52a10e2da07f4bac608228d1bed20bfebf2" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "jobserver" version = "0.1.32" @@ -2287,7 +2277,6 @@ dependencies = [ "ctrlc", "directories", "getrandom", - "jemalloc-sys", "libc", "libffi", "libloading", @@ -2297,6 +2286,7 @@ dependencies = [ "rustc_version", "smallvec", "tempfile", + "tikv-jemalloc-sys", "ui_test", "windows-sys 0.52.0", ] @@ -3151,12 +3141,12 @@ checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" name = "rustc-main" version = "0.0.0" dependencies = [ - "jemalloc-sys", "rustc_codegen_ssa", "rustc_driver", "rustc_driver_impl", "rustc_smir", "stable_mir", + "tikv-jemalloc-sys", ] [[package]] @@ -5260,6 +5250,16 @@ dependencies = [ name = "tier-check" version = "0.1.0" +[[package]] +name = "tikv-jemalloc-sys" +version = "0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd3c60906412afa9c2b5b5a48ca6a5abe5736aec9eb48ad05037a677e52e4e2d" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "time" version = "0.3.36" diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml index f85c30ac7ec..d24b630516a 100644 --- a/compiler/rustc/Cargo.toml +++ b/compiler/rustc/Cargo.toml @@ -20,14 +20,14 @@ rustc_smir = { path = "../rustc_smir" } stable_mir = { path = "../stable_mir" } # tidy-alphabetical-end -[dependencies.jemalloc-sys] -version = "0.5.0" +[dependencies.tikv-jemalloc-sys] +version = "0.6.0" optional = true features = ['unprefixed_malloc_on_supported_platforms'] [features] # tidy-alphabetical-start -jemalloc = ['dep:jemalloc-sys'] +jemalloc = ['dep:tikv-jemalloc-sys'] llvm = ['rustc_driver_impl/llvm'] max_level_info = ['rustc_driver_impl/max_level_info'] rustc_randomized_layouts = ['rustc_driver_impl/rustc_randomized_layouts'] diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs index ccf88d8ff4b..a55a63a7bf1 100644 --- a/compiler/rustc/src/main.rs +++ b/compiler/rustc/src/main.rs @@ -43,6 +43,8 @@ fn main() { { use std::os::raw::{c_int, c_void}; + use tikv_jemalloc_sys as jemalloc_sys; + #[used] static _F1: unsafe extern "C" fn(usize, usize) -> *mut c_void = jemalloc_sys::calloc; #[used] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 436d36d899e..8bc543f7e72 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -68,7 +68,7 @@ extern crate test; // See docs in https://github.com/rust-lang/rust/blob/master/compiler/rustc/src/main.rs // about jemalloc. #[cfg(feature = "jemalloc")] -extern crate jemalloc_sys; +extern crate tikv_jemalloc_sys as jemalloc_sys; use std::env::{self, VarError}; use std::io::{self, IsTerminal}; diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index cb02914fd93..473b4fba928 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -31,8 +31,8 @@ directories = "5" # Copied from `compiler/rustc/Cargo.toml`. # But only for some targets, it fails for others. Rustc configures this in its CI, but we can't # easily use that since we support of-tree builds. -[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies.jemalloc-sys] -version = "0.5.0" +[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies.tikv-jemalloc-sys] +version = "0.6.0" features = ['unprefixed_malloc_on_supported_platforms'] [target.'cfg(unix)'.dependencies] diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index c61c62c73da..1e0e31f01ab 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -316,6 +316,8 @@ fn jemalloc_magic() { // See there for further comments. use std::os::raw::{c_int, c_void}; + use tikv_jemalloc_sys as jemalloc_sys; + #[used] static _F1: unsafe extern "C" fn(usize, usize) -> *mut c_void = jemalloc_sys::calloc; #[used] diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index e065f01ebba..afa0b9a6760 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -307,7 +307,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "intl_pluralrules", "itertools", "itoa", - "jemalloc-sys", "jobserver", "lazy_static", "leb128", @@ -392,6 +391,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "thiserror-impl", "thorin-dwp", "thread_local", + "tikv-jemalloc-sys", "time", "time-core", "time-macros", -- cgit 1.4.1-3-g733a5 From c0a00b73f82a0e46155b342d62a44ba47fff5b15 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 3 Dec 2024 10:21:12 -0800 Subject: Update wasm-component-ld to 0.5.11 This pulls in an update that supports `@`-files used to pass arguments to linkers to fix invocations on Windows that are large. Closes #133649 --- Cargo.lock | 13 +++++++++++-- src/tools/wasm-component-ld/Cargo.toml | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'src/tools') diff --git a/Cargo.lock b/Cargo.lock index a96e0685858..f59dcdcf28d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5803,17 +5803,20 @@ checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "wasm-component-ld" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4aa6bd7fbe7cffbed29fe3e236fda74419def1bdef6f80f989ec51137edf44" +checksum = "a2b05c3820968b335f10e703218459e4fd2cc91fdfc8f7936a993f1aacaa0938" dependencies = [ "anyhow", "clap", "lexopt", + "libc", "tempfile", "wasi-preview1-component-adapter-provider", "wasmparser 0.219.1", "wat", + "windows-sys 0.59.0", + "winsplit", "wit-component", "wit-parser", ] @@ -6185,6 +6188,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "winsplit" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab703352da6a72f35c39a533526393725640575bb211f61987a2748323ad956" + [[package]] name = "wit-component" version = "0.219.1" diff --git a/src/tools/wasm-component-ld/Cargo.toml b/src/tools/wasm-component-ld/Cargo.toml index acdb1aa1ab7..965e9b01a44 100644 --- a/src/tools/wasm-component-ld/Cargo.toml +++ b/src/tools/wasm-component-ld/Cargo.toml @@ -10,4 +10,4 @@ name = "wasm-component-ld" path = "src/main.rs" [dependencies] -wasm-component-ld = "0.5.10" +wasm-component-ld = "0.5.11" -- cgit 1.4.1-3-g733a5 From ab38efefae34f9d69f92f09376eb40482b871de1 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Tue, 3 Dec 2024 18:43:22 +0000 Subject: compiletest: explain that UI tests are expected not to compile by default --- src/tools/compiletest/src/runtest.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/tools') diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 7be9e2f2d57..84269fd44a1 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -350,10 +350,13 @@ impl<'test> TestCx<'test> { } } else { if proc_res.status.success() { - self.fatal_proc_rec( - &format!("{} test compiled successfully!", self.config.mode)[..], - proc_res, - ); + { + self.error(&format!("{} test did not emit an error", self.config.mode)); + if self.config.mode == crate::common::Mode::Ui { + println!("note: by default, ui tests are expected not to compile"); + } + proc_res.fatal(None, || ()); + }; } if !self.props.dont_check_failure_status { -- cgit 1.4.1-3-g733a5 From 733871099c3da6c5ff37048a6ee81564385cf779 Mon Sep 17 00:00:00 2001 From: Jakub Beránek Date: Tue, 3 Dec 2024 21:59:41 +0100 Subject: Fix typo --- src/tools/tidy/src/ext_tool_checks.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/tools') diff --git a/src/tools/tidy/src/ext_tool_checks.rs b/src/tools/tidy/src/ext_tool_checks.rs index 8f21338c7db..bf1a3338797 100644 --- a/src/tools/tidy/src/ext_tool_checks.rs +++ b/src/tools/tidy/src/ext_tool_checks.rs @@ -34,7 +34,7 @@ const REL_PY_PATH: &[&str] = &["bin", "python3"]; const RUFF_CONFIG_PATH: &[&str] = &["src", "tools", "tidy", "config", "ruff.toml"]; const BLACK_CONFIG_PATH: &[&str] = &["src", "tools", "tidy", "config", "black.toml"]; /// Location within build directory -const RUFF_CACH_PATH: &[&str] = &["cache", "ruff_cache"]; +const RUFF_CACHE_PATH: &[&str] = &["cache", "ruff_cache"]; const PIP_REQ_PATH: &[&str] = &["src", "tools", "tidy", "config", "requirements.txt"]; pub fn check( @@ -96,7 +96,7 @@ fn check_impl( let mut cfg_path = root_path.to_owned(); cfg_path.extend(RUFF_CONFIG_PATH); let mut cache_dir = outdir.to_owned(); - cache_dir.extend(RUFF_CACH_PATH); + cache_dir.extend(RUFF_CACHE_PATH); cfg_args_ruff.extend([ "--config".as_ref(), -- cgit 1.4.1-3-g733a5 From f676ed2d2cb4cb96acc35b95b4c9ffefc4fc7737 Mon Sep 17 00:00:00 2001 From: Jakub Beránek Date: Tue, 3 Dec 2024 22:02:15 +0100 Subject: Fix copy-pasted tool name --- src/tools/tidy/src/ext_tool_checks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/tools') diff --git a/src/tools/tidy/src/ext_tool_checks.rs b/src/tools/tidy/src/ext_tool_checks.rs index bf1a3338797..f10844435d9 100644 --- a/src/tools/tidy/src/ext_tool_checks.rs +++ b/src/tools/tidy/src/ext_tool_checks.rs @@ -445,7 +445,7 @@ fn shellcheck_runner(args: &[&OsStr]) -> Result<(), Error> { } let status = Command::new("shellcheck").args(args).status()?; - if status.success() { Ok(()) } else { Err(Error::FailedCheck("black")) } + if status.success() { Ok(()) } else { Err(Error::FailedCheck("shellcheck")) } } /// Check git for tracked files matching an extension -- cgit 1.4.1-3-g733a5 From b24d608967183b940f79c1edd3a596d3eae9044e Mon Sep 17 00:00:00 2001 From: Jakub Beránek Date: Tue, 3 Dec 2024 22:02:58 +0100 Subject: Replace `black` with `ruff` for formatting Python code --- src/tools/tidy/src/ext_tool_checks.rs | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'src/tools') diff --git a/src/tools/tidy/src/ext_tool_checks.rs b/src/tools/tidy/src/ext_tool_checks.rs index f10844435d9..9792650d37d 100644 --- a/src/tools/tidy/src/ext_tool_checks.rs +++ b/src/tools/tidy/src/ext_tool_checks.rs @@ -32,7 +32,6 @@ const REL_PY_PATH: &[&str] = &["Scripts", "python3.exe"]; const REL_PY_PATH: &[&str] = &["bin", "python3"]; const RUFF_CONFIG_PATH: &[&str] = &["src", "tools", "tidy", "config", "ruff.toml"]; -const BLACK_CONFIG_PATH: &[&str] = &["src", "tools", "tidy", "config", "black.toml"]; /// Location within build directory const RUFF_CACHE_PATH: &[&str] = &["cache", "ruff_cache"]; const PIP_REQ_PATH: &[&str] = &["src", "tools", "tidy", "config", "requirements.txt"]; @@ -124,33 +123,36 @@ fn check_impl( } if python_fmt { - let mut cfg_args_black = cfg_args.clone(); - let mut file_args_black = file_args.clone(); + let mut cfg_args_ruff = cfg_args.clone(); + let mut file_args_ruff = file_args.clone(); if bless { eprintln!("formatting python files"); } else { eprintln!("checking python file formatting"); - cfg_args_black.push("--check".as_ref()); + cfg_args_ruff.push("--check".as_ref()); } let mut cfg_path = root_path.to_owned(); - cfg_path.extend(BLACK_CONFIG_PATH); + cfg_path.extend(RUFF_CONFIG_PATH); + let mut cache_dir = outdir.to_owned(); + cache_dir.extend(RUFF_CACHE_PATH); - cfg_args_black.extend(["--config".as_ref(), cfg_path.as_os_str()]); + cfg_args_ruff.extend(["--config".as_ref(), cfg_path.as_os_str()]); - if file_args_black.is_empty() { - file_args_black.push(root_path.as_os_str()); + if file_args_ruff.is_empty() { + file_args_ruff.push(root_path.as_os_str()); } - let mut args = merge_args(&cfg_args_black, &file_args_black); - let res = py_runner(py_path.as_ref().unwrap(), true, None, "black", &args); + let mut args = merge_args(&cfg_args_ruff, &file_args_ruff); + args.insert(0, "format".as_ref()); + let res = py_runner(py_path.as_ref().unwrap(), true, None, "ruff", &args); if res.is_err() && show_diff { eprintln!("\npython formatting does not match! Printing diff:"); args.insert(0, "--diff".as_ref()); - let _ = py_runner(py_path.as_ref().unwrap(), true, None, "black", &args); + let _ = py_runner(py_path.as_ref().unwrap(), true, None, "ruff", &args); } // Rethrow error let _ = res?; -- cgit 1.4.1-3-g733a5 From d5eb93b7e78105d51b7a77bbbee62cee6aabf078 Mon Sep 17 00:00:00 2001 From: Jakub Beránek Date: Tue, 3 Dec 2024 22:06:38 +0100 Subject: Remove dependency on `black` --- src/tools/tidy/config/black.toml | 18 ------------ src/tools/tidy/config/requirements.in | 1 - src/tools/tidy/config/requirements.txt | 52 ---------------------------------- 3 files changed, 71 deletions(-) delete mode 100644 src/tools/tidy/config/black.toml (limited to 'src/tools') diff --git a/src/tools/tidy/config/black.toml b/src/tools/tidy/config/black.toml deleted file mode 100644 index d5b8b198afb..00000000000 --- a/src/tools/tidy/config/black.toml +++ /dev/null @@ -1,18 +0,0 @@ -[tool.black] -# Ignore all submodules -extend-exclude = """(\ - src/doc/nomicon|\ - src/tools/cargo/|\ - src/doc/reference/|\ - src/doc/book/|\ - src/doc/rust-by-example/|\ - library/stdarch/|\ - src/doc/rustc-dev-guide/|\ - src/doc/edition-guide/|\ - src/llvm-project/|\ - src/doc/embedded-book/|\ - src/tools/rustc-perf/|\ - src/tools/enzyme/|\ - library/backtrace/|\ - src/gcc/ - )""" diff --git a/src/tools/tidy/config/requirements.in b/src/tools/tidy/config/requirements.in index 8938dc03243..1b2c38f2b5d 100644 --- a/src/tools/tidy/config/requirements.in +++ b/src/tools/tidy/config/requirements.in @@ -6,6 +6,5 @@ # Note: this generation step should be run with the oldest supported python # version (currently 3.9) to ensure backward compatibility -black==24.4.2 ruff==0.4.9 clang-format==18.1.7 diff --git a/src/tools/tidy/config/requirements.txt b/src/tools/tidy/config/requirements.txt index 790eabf5cf8..938179d5b3e 100644 --- a/src/tools/tidy/config/requirements.txt +++ b/src/tools/tidy/config/requirements.txt @@ -4,30 +4,6 @@ # # pip-compile --generate-hashes --strip-extras src/tools/tidy/config/requirements.in # -black==24.4.2 \ - --hash=sha256:257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474 \ - --hash=sha256:37aae07b029fa0174d39daf02748b379399b909652a806e5708199bd93899da1 \ - --hash=sha256:415e686e87dbbe6f4cd5ef0fbf764af7b89f9057b97c908742b6008cc554b9c0 \ - --hash=sha256:48a85f2cb5e6799a9ef05347b476cce6c182d6c71ee36925a6c194d074336ef8 \ - --hash=sha256:7768a0dbf16a39aa5e9a3ded568bb545c8c2727396d063bbaf847df05b08cd96 \ - --hash=sha256:7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1 \ - --hash=sha256:88c57dc656038f1ab9f92b3eb5335ee9b021412feaa46330d5eba4e51fe49b04 \ - --hash=sha256:8e537d281831ad0e71007dcdcbe50a71470b978c453fa41ce77186bbe0ed6021 \ - --hash=sha256:98e123f1d5cfd42f886624d84464f7756f60ff6eab89ae845210631714f6db94 \ - --hash=sha256:accf49e151c8ed2c0cdc528691838afd217c50412534e876a19270fea1e28e2d \ - --hash=sha256:b1530ae42e9d6d5b670a34db49a94115a64596bc77710b1d05e9801e62ca0a7c \ - --hash=sha256:b9176b9832e84308818a99a561e90aa479e73c523b3f77afd07913380ae2eab7 \ - --hash=sha256:bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c \ - --hash=sha256:be8bef99eb46d5021bf053114442914baeb3649a89dc5f3a555c88737e5e98fc \ - --hash=sha256:bf10f7310db693bb62692609b397e8d67257c55f949abde4c67f9cc574492cc7 \ - --hash=sha256:c872b53057f000085da66a19c55d68f6f8ddcac2642392ad3a355878406fbd4d \ - --hash=sha256:d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c \ - --hash=sha256:da33a1a5e49c4122ccdfd56cd021ff1ebc4a1ec4e2d01594fef9b6f267a9e741 \ - --hash=sha256:dd1b5a14e417189db4c7b64a6540f31730713d173f0b63e55fabd52d61d8fdce \ - --hash=sha256:e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb \ - --hash=sha256:eaea3008c281f1038edb473c1aa8ed8143a5535ff18f978a318f10302b254063 \ - --hash=sha256:ef703f83fc32e131e9bcc0a5094cfe85599e7109f896fe8bc96cc402f3eb4b6e - # via -r src/tools/tidy/config/requirements.in clang-format==18.1.7 \ --hash=sha256:035204410f65d03f98cb81c9c39d6d193f9987917cc88de9d0dbd01f2aa9c302 \ --hash=sha256:05c482a854287a5d21f7567186c0bd4b8dbd4a871751e655a45849185f30b931 \ @@ -45,26 +21,6 @@ clang-format==18.1.7 \ --hash=sha256:f4f77ac0f4f9a659213fedda0f2d216886c410132e6e7dd4b13f92b34e925554 \ --hash=sha256:f935d34152a2e11e55120eb9182862f432bc9789ab819f680c9f6db4edebf9e3 # via -r src/tools/tidy/config/requirements.in -click==8.1.3 \ - --hash=sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e \ - --hash=sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48 - # via black -mypy-extensions==1.0.0 \ - --hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \ - --hash=sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782 - # via black -packaging==23.1 \ - --hash=sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61 \ - --hash=sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f - # via black -pathspec==0.11.1 \ - --hash=sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687 \ - --hash=sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293 - # via black -platformdirs==4.2.2 \ - --hash=sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee \ - --hash=sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3 - # via black ruff==0.4.9 \ --hash=sha256:06b60f91bfa5514bb689b500a25ba48e897d18fea14dce14b48a0c40d1635893 \ --hash=sha256:0e8e7b95673f22e0efd3571fb5b0cf71a5eaaa3cc8a776584f3b2cc878e46bff \ @@ -84,11 +40,3 @@ ruff==0.4.9 \ --hash=sha256:e91175fbe48f8a2174c9aad70438fe9cb0a5732c4159b2a10a3565fea2d94cde \ --hash=sha256:f1cb0828ac9533ba0135d148d214e284711ede33640465e706772645483427e3 # via -r src/tools/tidy/config/requirements.in -tomli==2.0.1 \ - --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ - --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f - # via black -typing-extensions==4.12.2 \ - --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ - --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 - # via black -- cgit 1.4.1-3-g733a5 From 244afb94d4c4098882d924db7f4e6129eabacade Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 3 Dec 2024 16:46:51 -0500 Subject: Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/tools') diff --git a/src/tools/cargo b/src/tools/cargo index 4c39aaff668..05f54fdc343 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 4c39aaff66862cc0da52fe529aa1990bb8bb9a22 +Subproject commit 05f54fdc34310f458033af8a63ce1d699fae8bf6 -- cgit 1.4.1-3-g733a5 From 23725619c416a62508cc9b1876b0ee9080dabfbe Mon Sep 17 00:00:00 2001 From: clubby789 Date: Tue, 3 Dec 2024 20:21:51 +0000 Subject: compiletest: `println!` -> `eprintln!` --- src/tools/compiletest/src/compute_diff.rs | 2 +- src/tools/compiletest/src/debuggers.rs | 6 +-- src/tools/compiletest/src/lib.rs | 10 ++--- src/tools/compiletest/src/runtest.rs | 50 +++++++++++----------- src/tools/compiletest/src/runtest/codegen_units.rs | 22 +++++----- src/tools/compiletest/src/runtest/debuginfo.rs | 10 ++--- src/tools/compiletest/src/runtest/rustdoc_json.rs | 2 +- src/tools/compiletest/src/runtest/ui.rs | 4 +- src/tools/compiletest/src/util.rs | 2 +- 9 files changed, 54 insertions(+), 54 deletions(-) (limited to 'src/tools') diff --git a/src/tools/compiletest/src/compute_diff.rs b/src/tools/compiletest/src/compute_diff.rs index 92c80c27de0..3ace6c5b6d7 100644 --- a/src/tools/compiletest/src/compute_diff.rs +++ b/src/tools/compiletest/src/compute_diff.rs @@ -144,7 +144,7 @@ where } if !wrote_data { - println!("note: diff is identical to nightly rustdoc"); + eprintln!("note: diff is identical to nightly rustdoc"); assert!(diff_output.metadata().unwrap().len() == 0); return false; } else if verbose { diff --git a/src/tools/compiletest/src/debuggers.rs b/src/tools/compiletest/src/debuggers.rs index b605bc813f1..e75c8a5993e 100644 --- a/src/tools/compiletest/src/debuggers.rs +++ b/src/tools/compiletest/src/debuggers.rs @@ -20,7 +20,7 @@ pub(crate) fn configure_gdb(config: &Config) -> Option> { } if config.remote_test_client.is_some() && !config.target.contains("android") { - println!( + eprintln!( "WARNING: debuginfo tests are not available when \ testing with remote" ); @@ -28,7 +28,7 @@ pub(crate) fn configure_gdb(config: &Config) -> Option> { } if config.target.contains("android") { - println!( + eprintln!( "{} debug-info test uses tcp 5039 port.\ please reserve it", config.target @@ -50,7 +50,7 @@ pub(crate) fn configure_lldb(config: &Config) -> Option> { config.lldb_python_dir.as_ref()?; if let Some(350) = config.lldb_version { - println!( + eprintln!( "WARNING: The used version of LLDB (350) has a \ known issue that breaks debuginfo tests. See \ issue #32520 for more information. Skipping all \ diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index bf4a3124075..447568065f5 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -188,8 +188,8 @@ pub fn parse_config(args: Vec) -> Config { let (argv0, args_) = args.split_first().unwrap(); if args.len() == 1 || args[1] == "-h" || args[1] == "--help" { let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0); - println!("{}", opts.usage(&message)); - println!(); + eprintln!("{}", opts.usage(&message)); + eprintln!(); panic!() } @@ -200,8 +200,8 @@ pub fn parse_config(args: Vec) -> Config { if matches.opt_present("h") || matches.opt_present("help") { let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0); - println!("{}", opts.usage(&message)); - println!(); + eprintln!("{}", opts.usage(&message)); + eprintln!(); panic!() } @@ -501,7 +501,7 @@ pub fn run_tests(config: Arc) { // easy to miss which tests failed, and as such fail to reproduce // the failure locally. - println!( + eprintln!( "Some tests failed in compiletest suite={}{} mode={} host={} target={}", config.suite, config diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 7be9e2f2d57..7098b9449a3 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -771,20 +771,20 @@ impl<'test> TestCx<'test> { unexpected.len(), not_found.len() )); - println!("status: {}\ncommand: {}\n", proc_res.status, proc_res.cmdline); + eprintln!("status: {}\ncommand: {}\n", proc_res.status, proc_res.cmdline); if !unexpected.is_empty() { - println!("{}", "--- unexpected errors (from JSON output) ---".green()); + eprintln!("{}", "--- unexpected errors (from JSON output) ---".green()); for error in &unexpected { - println!("{}", error.render_for_expected()); + eprintln!("{}", error.render_for_expected()); } - println!("{}", "---".green()); + eprintln!("{}", "---".green()); } if !not_found.is_empty() { - println!("{}", "--- not found errors (from test file) ---".red()); + eprintln!("{}", "--- not found errors (from test file) ---".red()); for error in ¬_found { - println!("{}", error.render_for_expected()); + eprintln!("{}", error.render_for_expected()); } - println!("{}", "---\n".red()); + eprintln!("{}", "---\n".red()); } panic!("errors differ from expected"); } @@ -1873,18 +1873,18 @@ impl<'test> TestCx<'test> { fn maybe_dump_to_stdout(&self, out: &str, err: &str) { if self.config.verbose { - println!("------stdout------------------------------"); - println!("{}", out); - println!("------stderr------------------------------"); - println!("{}", err); - println!("------------------------------------------"); + eprintln!("------stdout------------------------------"); + eprintln!("{}", out); + eprintln!("------stderr------------------------------"); + eprintln!("{}", err); + eprintln!("------------------------------------------"); } } fn error(&self, err: &str) { match self.revision { - Some(rev) => println!("\nerror in revision `{}`: {}", rev, err), - None => println!("\nerror: {}", err), + Some(rev) => eprintln!("\nerror in revision `{}`: {}", rev, err), + None => eprintln!("\nerror: {}", err), } } @@ -1969,7 +1969,7 @@ impl<'test> TestCx<'test> { if !self.config.has_html_tidy { return; } - println!("info: generating a diff against nightly rustdoc"); + eprintln!("info: generating a diff against nightly rustdoc"); let suffix = self.safe_revision().map_or("nightly".into(), |path| path.to_owned() + "-nightly"); @@ -2079,7 +2079,7 @@ impl<'test> TestCx<'test> { .output() .unwrap(); assert!(output.status.success()); - println!("{}", String::from_utf8_lossy(&output.stdout)); + eprintln!("{}", String::from_utf8_lossy(&output.stdout)); eprintln!("{}", String::from_utf8_lossy(&output.stderr)); } else { use colored::Colorize; @@ -2479,7 +2479,7 @@ impl<'test> TestCx<'test> { )"# ) .replace_all(&output, |caps: &Captures<'_>| { - println!("{}", &caps[0]); + eprintln!("{}", &caps[0]); caps[0].replace(r"\", "/") }) .replace("\r\n", "\n") @@ -2578,16 +2578,16 @@ impl<'test> TestCx<'test> { if let Err(err) = fs::write(&actual_path, &actual) { self.fatal(&format!("failed to write {stream} to `{actual_path:?}`: {err}",)); } - println!("Saved the actual {stream} to {actual_path:?}"); + eprintln!("Saved the actual {stream} to {actual_path:?}"); let expected_path = expected_output_path(self.testpaths, self.revision, &self.config.compare_mode, stream); if !self.config.bless { if expected.is_empty() { - println!("normalized {}:\n{}\n", stream, actual); + eprintln!("normalized {}:\n{}\n", stream, actual); } else { - println!("diff of {stream}:\n"); + eprintln!("diff of {stream}:\n"); if let Some(diff_command) = self.config.diff_command.as_deref() { let mut args = diff_command.split_whitespace(); let name = args.next().unwrap(); @@ -2622,10 +2622,10 @@ impl<'test> TestCx<'test> { if let Err(err) = fs::write(&expected_path, &actual) { self.fatal(&format!("failed to write {stream} to `{expected_path:?}`: {err}")); } - println!("Blessing the {stream} of {test_name} in {expected_path:?}"); + eprintln!("Blessing the {stream} of {test_name} in {expected_path:?}"); } - println!("\nThe actual {0} differed from the expected {0}.", stream); + eprintln!("\nThe actual {0} differed from the expected {0}.", stream); if self.config.bless { 0 } else { 1 } } @@ -2704,7 +2704,7 @@ impl<'test> TestCx<'test> { fs::create_dir_all(&incremental_dir).unwrap(); if self.config.verbose { - println!("init_incremental_test: incremental_dir={}", incremental_dir.display()); + eprintln!("init_incremental_test: incremental_dir={}", incremental_dir.display()); } } @@ -2762,7 +2762,7 @@ impl ProcRes { } } - println!( + eprintln!( "status: {}\ncommand: {}\n{}\n{}\n", self.status, self.cmdline, @@ -2773,7 +2773,7 @@ impl ProcRes { pub fn fatal(&self, err: Option<&str>, on_failure: impl FnOnce()) -> ! { if let Some(e) = err { - println!("\nerror: {}", e); + eprintln!("\nerror: {}", e); } self.print_info(); on_failure(); diff --git a/src/tools/compiletest/src/runtest/codegen_units.rs b/src/tools/compiletest/src/runtest/codegen_units.rs index 6c866cbef21..6acd140183d 100644 --- a/src/tools/compiletest/src/runtest/codegen_units.rs +++ b/src/tools/compiletest/src/runtest/codegen_units.rs @@ -64,13 +64,13 @@ impl TestCx<'_> { if !missing.is_empty() { missing.sort(); - println!("\nThese items should have been contained but were not:\n"); + eprintln!("\nThese items should have been contained but were not:\n"); for item in &missing { - println!("{}", item); + eprintln!("{}", item); } - println!("\n"); + eprintln!("\n"); } if !unexpected.is_empty() { @@ -80,24 +80,24 @@ impl TestCx<'_> { sorted }; - println!("\nThese items were contained but should not have been:\n"); + eprintln!("\nThese items were contained but should not have been:\n"); for item in sorted { - println!("{}", item); + eprintln!("{}", item); } - println!("\n"); + eprintln!("\n"); } if !wrong_cgus.is_empty() { wrong_cgus.sort_by_key(|pair| pair.0.name.clone()); - println!("\nThe following items were assigned to wrong codegen units:\n"); + eprintln!("\nThe following items were assigned to wrong codegen units:\n"); for &(ref expected_item, ref actual_item) in &wrong_cgus { - println!("{}", expected_item.name); - println!(" expected: {}", codegen_units_to_str(&expected_item.codegen_units)); - println!(" actual: {}", codegen_units_to_str(&actual_item.codegen_units)); - println!(); + eprintln!("{}", expected_item.name); + eprintln!(" expected: {}", codegen_units_to_str(&expected_item.codegen_units)); + eprintln!(" actual: {}", codegen_units_to_str(&actual_item.codegen_units)); + eprintln!(); } } diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs index c621c22ac99..7322e730e53 100644 --- a/src/tools/compiletest/src/runtest/debuginfo.rs +++ b/src/tools/compiletest/src/runtest/debuginfo.rs @@ -260,7 +260,7 @@ impl TestCx<'_> { cmdline, }; if adb.kill().is_err() { - println!("Adb process is already finished."); + eprintln!("Adb process is already finished."); } } else { let rust_src_root = @@ -275,7 +275,7 @@ impl TestCx<'_> { match self.config.gdb_version { Some(version) => { - println!("NOTE: compiletest thinks it is using GDB version {}", version); + eprintln!("NOTE: compiletest thinks it is using GDB version {}", version); if version > extract_gdb_version("7.4").unwrap() { // Add the directory containing the pretty printers to @@ -297,7 +297,7 @@ impl TestCx<'_> { } } _ => { - println!( + eprintln!( "NOTE: compiletest does not know which version of \ GDB it is using" ); @@ -392,10 +392,10 @@ impl TestCx<'_> { match self.config.lldb_version { Some(ref version) => { - println!("NOTE: compiletest thinks it is using LLDB version {}", version); + eprintln!("NOTE: compiletest thinks it is using LLDB version {}", version); } _ => { - println!( + eprintln!( "NOTE: compiletest does not know which version of \ LLDB it is using" ); diff --git a/src/tools/compiletest/src/runtest/rustdoc_json.rs b/src/tools/compiletest/src/runtest/rustdoc_json.rs index 31fdb0a5d13..84376d346af 100644 --- a/src/tools/compiletest/src/runtest/rustdoc_json.rs +++ b/src/tools/compiletest/src/runtest/rustdoc_json.rs @@ -29,7 +29,7 @@ impl TestCx<'_> { if !res.status.success() { self.fatal_proc_rec_with_ctx("jsondocck failed!", &res, |_| { - println!("Rustdoc Output:"); + eprintln!("Rustdoc Output:"); proc_res.print_info(); }) } diff --git a/src/tools/compiletest/src/runtest/ui.rs b/src/tools/compiletest/src/runtest/ui.rs index bb747c68029..414f1a6adb3 100644 --- a/src/tools/compiletest/src/runtest/ui.rs +++ b/src/tools/compiletest/src/runtest/ui.rs @@ -109,10 +109,10 @@ impl TestCx<'_> { } if errors > 0 { - println!("To update references, rerun the tests and pass the `--bless` flag"); + eprintln!("To update references, rerun the tests and pass the `--bless` flag"); let relative_path_to_file = self.testpaths.relative_dir.join(self.testpaths.file.file_name().unwrap()); - println!( + eprintln!( "To only update this specific test, also pass `--test-args {}`", relative_path_to_file.display(), ); diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index bff02f1db9f..7b50e62c29b 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -30,7 +30,7 @@ fn path_div() -> &'static str { pub fn logv(config: &Config, s: String) { debug!("{}", s); if config.verbose { - println!("{}", s); + eprintln!("{}", s); } } -- cgit 1.4.1-3-g733a5 From 8374f7ceb5d81cc0c540444cfce55594bad33d33 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Tue, 3 Dec 2024 20:23:14 +0000 Subject: tidy: `println!` -> `eprintln!` --- src/tools/tidy/src/error_codes.rs | 6 +++--- src/tools/tidy/src/features.rs | 8 ++++---- src/tools/tidy/src/unstable_book.rs | 8 ++++---- src/tools/tidy/src/x_version.rs | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src/tools') diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs index e2d1b85797f..9dc49b57d59 100644 --- a/src/tools/tidy/src/error_codes.rs +++ b/src/tools/tidy/src/error_codes.rs @@ -38,7 +38,7 @@ const IGNORE_UI_TEST_CHECK: &[&str] = macro_rules! verbose_print { ($verbose:expr, $($fmt:tt)*) => { if $verbose { - println!("{}", format_args!($($fmt)*)); + eprintln!("{}", format_args!($($fmt)*)); } }; } @@ -49,8 +49,8 @@ pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut // Stage 1: create list let error_codes = extract_error_codes(root_path, &mut errors); if verbose { - println!("Found {} error codes", error_codes.len()); - println!("Highest error code: `{}`", error_codes.iter().max().unwrap()); + eprintln!("Found {} error codes", error_codes.len()); + eprintln!("Highest error code: `{}`", error_codes.iter().max().unwrap()); } // Stage 2: check list has docs diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 4f24eb21242..4607d041577 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -158,14 +158,14 @@ pub fn check( .collect::>(); for &(name, _) in gate_untested.iter() { - println!("Expected a gate test for the feature '{name}'."); - println!( + eprintln!("Expected a gate test for the feature '{name}'."); + eprintln!( "Hint: create a failing test file named 'tests/ui/feature-gates/feature-gate-{}.rs',\ \n with its failures due to missing usage of `#![feature({})]`.", name.replace("_", "-"), name ); - println!( + eprintln!( "Hint: If you already have such a test and don't want to rename it,\ \n you can also add a // gate-test-{} line to the test file.", name @@ -218,7 +218,7 @@ pub fn check( lines.sort(); for line in lines { - println!("* {line}"); + eprintln!("* {line}"); } } diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs index 8be25b98df0..06d238ef5e4 100644 --- a/src/tools/tidy/src/unstable_book.rs +++ b/src/tools/tidy/src/unstable_book.rs @@ -118,16 +118,16 @@ pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) { // List unstable features that don't have Unstable Book sections. // Remove the comment marker if you want the list printed. /* - println!("Lib features without unstable book sections:"); + eprintln!("Lib features without unstable book sections:"); for feature_name in &unstable_lang_feature_names - &unstable_book_lang_features_section_file_names { - println!(" * {} {:?}", feature_name, lib_features[&feature_name].tracking_issue); + eprintln!(" * {} {:?}", feature_name, lib_features[&feature_name].tracking_issue); } - println!("Lang features without unstable book sections:"); + eprintln!("Lang features without unstable book sections:"); for feature_name in &unstable_lib_feature_names- &unstable_book_lib_features_section_file_names { - println!(" * {} {:?}", feature_name, lang_features[&feature_name].tracking_issue); + eprintln!(" * {} {:?}", feature_name, lang_features[&feature_name].tracking_issue); } // */ } diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs index 489343561e1..b43d56202c9 100644 --- a/src/tools/tidy/src/x_version.rs +++ b/src/tools/tidy/src/x_version.rs @@ -42,7 +42,7 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) { if let Some(expected) = get_x_wrapper_version(root, cargo) { if installed < expected { - return println!( + return eprintln!( "Current version of x is {installed}, but the latest version is {expected}\nConsider updating to the newer version of x by running `cargo install --path src/tools/x`" ); } -- cgit 1.4.1-3-g733a5 From db8bef50736160db2c06064fcdacda3c2e6dfeb0 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Wed, 4 Dec 2024 05:02:38 +0000 Subject: Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/tools') diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index e193c786eff..377639882c5 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -eddb717281a9031f645d88dd3b8323a7e25632cc +3b382642aba7cffbb2f47829b24635fad87bcf5c -- cgit 1.4.1-3-g733a5 From 6c9402012e4e442aff1194f1888f773fa93b9517 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Wed, 4 Dec 2024 05:12:09 +0000 Subject: fmt --- src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/tools') diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs index 4b49e105562..fd7fc801dc2 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs @@ -48,7 +48,11 @@ fn test_readlink() { // Test that we report a proper error for a missing path. let res = unsafe { - libc::readlink(c"MIRI_MISSING_FILE_NAME".as_ptr(), small_buf.as_mut_ptr().cast(), small_buf.len()) + libc::readlink( + c"MIRI_MISSING_FILE_NAME".as_ptr(), + small_buf.as_mut_ptr().cast(), + small_buf.len(), + ) }; assert_eq!(res, -1); assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound); -- cgit 1.4.1-3-g733a5 From 76c27a98495e5d61b32ad285e5d1a6533678cf38 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 4 Dec 2024 08:15:05 +0100 Subject: update lockfile --- src/tools/miri/Cargo.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src/tools') diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index 01e32229f25..363b96fdff1 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -403,16 +403,6 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" -[[package]] -name = "jemalloc-sys" -version = "0.5.4+5.3.0-patched" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac6c1946e1cea1788cbfde01c993b52a10e2da07f4bac608228d1bed20bfebf2" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "lazy_static" version = "1.5.0" @@ -540,7 +530,6 @@ dependencies = [ "colored", "directories", "getrandom", - "jemalloc-sys", "libc", "libffi", "libloading", @@ -550,6 +539,7 @@ dependencies = [ "rustc_version", "smallvec", "tempfile", + "tikv-jemalloc-sys", "ui_test", "windows-sys 0.52.0", ] @@ -1002,6 +992,16 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tikv-jemalloc-sys" +version = "0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd3c60906412afa9c2b5b5a48ca6a5abe5736aec9eb48ad05037a677e52e4e2d" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "tracing" version = "0.1.40" -- cgit 1.4.1-3-g733a5 From 91bd957a21bc936f2d8732c658c0f4a1737361b3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 4 Dec 2024 08:35:31 +0100 Subject: implement simd_relaxed_fma --- src/tools/miri/src/intrinsics/simd.rs | 17 +++- .../pass/intrinsics/fmuladd_nondeterministic.rs | 91 +++++++++++++++------- .../miri/tests/pass/intrinsics/portable-simd.rs | 22 ++++++ 3 files changed, 97 insertions(+), 33 deletions(-) (limited to 'src/tools') diff --git a/src/tools/miri/src/intrinsics/simd.rs b/src/tools/miri/src/intrinsics/simd.rs index 075b6f35e0e..54bdd3f02c2 100644 --- a/src/tools/miri/src/intrinsics/simd.rs +++ b/src/tools/miri/src/intrinsics/simd.rs @@ -1,4 +1,5 @@ use either::Either; +use rand::Rng; use rustc_abi::{Endian, HasDataLayout}; use rustc_apfloat::{Float, Round}; use rustc_middle::ty::FloatTy; @@ -286,7 +287,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(val, &dest)?; } } - "fma" => { + "fma" | "relaxed_fma" => { let [a, b, c] = check_arg_count(args)?; let (a, a_len) = this.project_to_simd(a)?; let (b, b_len) = this.project_to_simd(b)?; @@ -303,6 +304,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let c = this.read_scalar(&this.project_index(&c, i)?)?; let dest = this.project_index(&dest, i)?; + let fuse: bool = intrinsic_name == "fma" || this.machine.rng.get_mut().gen(); + // Works for f32 and f64. // FIXME: using host floats to work around https://github.com/rust-lang/miri/issues/2468. let ty::Float(float_ty) = dest.layout.ty.kind() else { @@ -314,7 +317,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let a = a.to_f32()?; let b = b.to_f32()?; let c = c.to_f32()?; - let res = a.to_host().mul_add(b.to_host(), c.to_host()).to_soft(); + let res = if fuse { + a.to_host().mul_add(b.to_host(), c.to_host()).to_soft() + } else { + ((a * b).value + c).value + }; let res = this.adjust_nan(res, &[a, b, c]); Scalar::from(res) } @@ -322,7 +329,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let a = a.to_f64()?; let b = b.to_f64()?; let c = c.to_f64()?; - let res = a.to_host().mul_add(b.to_host(), c.to_host()).to_soft(); + let res = if fuse { + a.to_host().mul_add(b.to_host(), c.to_host()).to_soft() + } else { + ((a * b).value + c).value + }; let res = this.adjust_nan(res, &[a, b, c]); Scalar::from(res) } diff --git a/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs b/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs index b46cf1ddf65..b688405c4b1 100644 --- a/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs +++ b/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs @@ -1,44 +1,75 @@ -#![feature(core_intrinsics)] +#![feature(core_intrinsics, portable_simd)] +use std::intrinsics::simd::simd_relaxed_fma; use std::intrinsics::{fmuladdf32, fmuladdf64}; +use std::simd::prelude::*; -fn main() { - let mut saw_zero = false; - let mut saw_nonzero = false; +fn ensure_both_happen(f: impl Fn() -> bool) -> bool { + let mut saw_true = false; + let mut saw_false = false; for _ in 0..50 { - let a = std::hint::black_box(0.1_f64); - let b = std::hint::black_box(0.2); - let c = std::hint::black_box(-a * b); - // It is unspecified whether the following operation is fused or not. The - // following evaluates to 0.0 if unfused, and nonzero (-1.66e-18) if fused. - let x = unsafe { fmuladdf64(a, b, c) }; - if x == 0.0 { - saw_zero = true; + let b = f(); + if b { + saw_true = true; } else { - saw_nonzero = true; + saw_false = true; + } + if saw_true && saw_false { + return true; } } + false +} + +fn main() { assert!( - saw_zero && saw_nonzero, + ensure_both_happen(|| { + let a = std::hint::black_box(0.1_f64); + let b = std::hint::black_box(0.2); + let c = std::hint::black_box(-a * b); + // It is unspecified whether the following operation is fused or not. The + // following evaluates to 0.0 if unfused, and nonzero (-1.66e-18) if fused. + let x = unsafe { fmuladdf64(a, b, c) }; + x == 0.0 + }), "`fmuladdf64` failed to be evaluated as both fused and unfused" ); - let mut saw_zero = false; - let mut saw_nonzero = false; - for _ in 0..50 { - let a = std::hint::black_box(0.1_f32); - let b = std::hint::black_box(0.2); - let c = std::hint::black_box(-a * b); - // It is unspecified whether the following operation is fused or not. The - // following evaluates to 0.0 if unfused, and nonzero (-8.1956386e-10) if fused. - let x = unsafe { fmuladdf32(a, b, c) }; - if x == 0.0 { - saw_zero = true; - } else { - saw_nonzero = true; - } - } assert!( - saw_zero && saw_nonzero, + ensure_both_happen(|| { + let a = std::hint::black_box(0.1_f32); + let b = std::hint::black_box(0.2); + let c = std::hint::black_box(-a * b); + // It is unspecified whether the following operation is fused or not. The + // following evaluates to 0.0 if unfused, and nonzero (-8.1956386e-10) if fused. + let x = unsafe { fmuladdf32(a, b, c) }; + x == 0.0 + }), "`fmuladdf32` failed to be evaluated as both fused and unfused" ); + + assert!( + ensure_both_happen(|| { + let a = f32x4::splat(std::hint::black_box(0.1)); + let b = f32x4::splat(std::hint::black_box(0.2)); + let c = std::hint::black_box(-a * b); + let x = unsafe { simd_relaxed_fma(a, b, c) }; + // Whether we fuse or not is a per-element decision, so sometimes these should be + // the same and sometimes not. + x[0] == x[1] + }), + "`simd_relaxed_fma` failed to be evaluated as both fused and unfused" + ); + + assert!( + ensure_both_happen(|| { + let a = f64x4::splat(std::hint::black_box(0.1)); + let b = f64x4::splat(std::hint::black_box(0.2)); + let c = std::hint::black_box(-a * b); + let x = unsafe { simd_relaxed_fma(a, b, c) }; + // Whether we fuse or not is a per-element decision, so sometimes these should be + // the same and sometimes not. + x[0] == x[1] + }), + "`simd_relaxed_fma` failed to be evaluated as both fused and unfused" + ); } diff --git a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs index f560669dd63..acd3502f528 100644 --- a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs +++ b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs @@ -40,6 +40,17 @@ fn simd_ops_f32() { f32x4::splat(-3.2).mul_add(b, f32x4::splat(f32::NEG_INFINITY)), f32x4::splat(f32::NEG_INFINITY) ); + + unsafe { + assert_eq!(intrinsics::simd_relaxed_fma(a, b, a), (a * b) + a); + assert_eq!(intrinsics::simd_relaxed_fma(b, b, a), (b * b) + a); + assert_eq!(intrinsics::simd_relaxed_fma(a, b, b), (a * b) + b); + assert_eq!( + intrinsics::simd_relaxed_fma(f32x4::splat(-3.2), b, f32x4::splat(f32::NEG_INFINITY)), + f32x4::splat(f32::NEG_INFINITY) + ); + } + assert_eq!((a * a).sqrt(), a); assert_eq!((b * b).sqrt(), b.abs()); @@ -94,6 +105,17 @@ fn simd_ops_f64() { f64x4::splat(-3.2).mul_add(b, f64x4::splat(f64::NEG_INFINITY)), f64x4::splat(f64::NEG_INFINITY) ); + + unsafe { + assert_eq!(intrinsics::simd_relaxed_fma(a, b, a), (a * b) + a); + assert_eq!(intrinsics::simd_relaxed_fma(b, b, a), (b * b) + a); + assert_eq!(intrinsics::simd_relaxed_fma(a, b, b), (a * b) + b); + assert_eq!( + intrinsics::simd_relaxed_fma(f64x4::splat(-3.2), b, f64x4::splat(f64::NEG_INFINITY)), + f64x4::splat(f64::NEG_INFINITY) + ); + } + assert_eq!((a * a).sqrt(), a); assert_eq!((b * b).sqrt(), b.abs()); -- cgit 1.4.1-3-g733a5 From fceb304dfd38b3eda17bea19128488de43cfb691 Mon Sep 17 00:00:00 2001 From: Johannes Hostert Date: Mon, 26 Aug 2024 22:40:17 +0200 Subject: Properly fix #3846 by resetting parents on lazy node creation This commit supplies a real fix, which makes retags more complicated, at the benefit of making accesses more performant. Co-authored-by: Ralf Jung --- .../tree_borrows/foreign_access_skipping.rs | 108 ++++++++++++ .../miri/src/borrow_tracker/tree_borrows/mod.rs | 10 +- .../miri/src/borrow_tracker/tree_borrows/perms.rs | 61 ++++++- .../miri/src/borrow_tracker/tree_borrows/tree.rs | 190 ++++++++++++--------- .../src/borrow_tracker/tree_borrows/tree/tests.rs | 27 ++- 5 files changed, 306 insertions(+), 90 deletions(-) create mode 100644 src/tools/miri/src/borrow_tracker/tree_borrows/foreign_access_skipping.rs (limited to 'src/tools') diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/foreign_access_skipping.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/foreign_access_skipping.rs new file mode 100644 index 00000000000..928b3e6baef --- /dev/null +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/foreign_access_skipping.rs @@ -0,0 +1,108 @@ +use super::AccessKind; +use super::tree::AccessRelatedness; + +/// To speed up tree traversals, we want to skip traversing subtrees when we know the traversal will have no effect. +/// This is often the case for foreign accesses, since usually foreign accesses happen several times in a row, but also +/// foreign accesses are idempotent. In particular, see tests `foreign_read_is_noop_after_foreign_write` and `all_transitions_idempotent`. +/// Thus, for each node we keep track of the "strongest idempotent foreign access" (SIFA), i.e. which foreign access can be skipped. +/// Note that for correctness, it is not required that this is the strongest access, just any access it is idempotent under. In particular, setting +/// it to `None` is always correct, but the point of this optimization is to have it be as strong as possible so that more accesses can be skipped. +/// This enum represents the kinds of values we store: +/// - `None` means that the node (and its subtrees) are not (guaranteed to be) idempotent under any foreign access. +/// - `Read` means that the node (and its subtrees) are idempotent under foreign reads, but not (yet / necessarily) under foreign writes. +/// - `Write` means that the node (and its subtrees) are idempotent under foreign writes. This also implies that it is idempotent under foreign +/// reads, since reads are stronger than writes (see test `foreign_read_is_noop_after_foreign_write`). In other words, this node can be skipped +/// for all foreign accesses. +/// +/// Since a traversal does not just visit a node, but instead the entire subtree, the SIFA field for a given node indicates that the access to +/// *the entire subtree* rooted at that node can be skipped. In order for this to work, we maintain the global invariant that at +/// each location, the SIFA at each child must be stronger than that at the parent. For normal reads and writes, this is easily accomplished by +/// tracking each foreign access as it occurs, so that then the next access can be skipped. This also obviously maintains the invariant, because +/// if a node undergoes a foreign access, then all its children also see this as a foreign access. However, the invariant is broken during retags, +/// because retags act across the entire allocation, but only emit a read event across a specific range. This means that for all nodes outside that +/// range, the invariant is potentially broken, since a new child with a weaker SIFA is inserted. Thus, during retags, special care is taken to +/// "manually" reset the parent's SIFA to be at least as strong as the new child's. This is accomplished with the `ensure_no_stronger_than` method. +/// +/// Note that we derive Ord and PartialOrd, so the order in which variants are listed below matters: +/// None < Read < Write. Do not change that order. See the `test_order` test. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)] +pub enum IdempotentForeignAccess { + #[default] + None, + Read, + Write, +} + +impl IdempotentForeignAccess { + /// Returns true if a node where the strongest idempotent foreign access is `self` + /// can skip the access `happening_next`. Note that if this returns + /// `true`, then the entire subtree will be skipped. + pub fn can_skip_foreign_access(self, happening_next: IdempotentForeignAccess) -> bool { + debug_assert!(happening_next.is_foreign()); + // This ordering is correct. Intuitively, if the last access here was + // a foreign write, everything can be skipped, since after a foreign write, + // all further foreign accesses are idempotent + happening_next <= self + } + + /// Updates `self` to account for a foreign access. + pub fn record_new(&mut self, just_happened: IdempotentForeignAccess) { + if just_happened.is_local() { + // If the access is local, reset it. + *self = IdempotentForeignAccess::None; + } else { + // Otherwise, keep it or stengthen it. + *self = just_happened.max(*self); + } + } + + /// Returns true if this access is local. + pub fn is_local(self) -> bool { + matches!(self, IdempotentForeignAccess::None) + } + + /// Returns true if this access is foreign, i.e. not local. + pub fn is_foreign(self) -> bool { + !self.is_local() + } + + /// Constructs a foreign access from an `AccessKind` + pub fn from_foreign(acc: AccessKind) -> IdempotentForeignAccess { + match acc { + AccessKind::Read => Self::Read, + AccessKind::Write => Self::Write, + } + } + + /// Usually, tree traversals have an `AccessKind` and an `AccessRelatedness`. + /// This methods converts these into the corresponding `IdempotentForeignAccess`, to be used + /// to e.g. invoke `can_skip_foreign_access`. + pub fn from_acc_and_rel(acc: AccessKind, rel: AccessRelatedness) -> IdempotentForeignAccess { + if rel.is_foreign() { Self::from_foreign(acc) } else { Self::None } + } + + /// During retags, the SIFA needs to be weakened to account for children with weaker SIFAs being inserted. + /// Thus, this method is called from the bottom up on each parent, until it returns false, which means the + /// "children have stronger SIFAs" invariant is restored. + pub fn ensure_no_stronger_than(&mut self, strongest_allowed: IdempotentForeignAccess) -> bool { + if *self > strongest_allowed { + *self = strongest_allowed; + true + } else { + false + } + } +} + +#[cfg(test)] +mod tests { + use super::IdempotentForeignAccess; + + #[test] + fn test_order() { + // The internal logic relies on this order. + // Do not change. + assert!(IdempotentForeignAccess::None < IdempotentForeignAccess::Read); + assert!(IdempotentForeignAccess::Read < IdempotentForeignAccess::Write); + } +} diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 40467aa4bc1..37fbcc7e3a4 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -9,6 +9,7 @@ use crate::concurrency::data_race::NaReadType; use crate::*; pub mod diagnostics; +mod foreign_access_skipping; mod perms; mod tree; mod unimap; @@ -296,7 +297,14 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.machine.current_span(), )?; // Record the parent-child pair in the tree. - tree_borrows.new_child(orig_tag, new_tag, new_perm.initial_state, range, span)?; + tree_borrows.new_child( + orig_tag, + new_tag, + new_perm.initial_state, + range, + span, + new_perm.protector.is_some(), + )?; drop(tree_borrows); // Also inform the data race model (but only if any bytes are actually affected). diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs index 28f9dec7bb9..6e157d3fcd3 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs @@ -48,6 +48,7 @@ enum PermissionPriv { Disabled, } use self::PermissionPriv::*; +use super::foreign_access_skipping::IdempotentForeignAccess; impl PartialOrd for PermissionPriv { /// PermissionPriv is ordered by the reflexive transitive closure of @@ -87,6 +88,28 @@ impl PermissionPriv { fn compatible_with_protector(&self) -> bool { !matches!(self, ReservedIM) } + + /// See `foreign_access_skipping.rs`. Computes the SIFA of a permission. + fn strongest_idempotent_foreign_access(&self, prot: bool) -> IdempotentForeignAccess { + match self { + // A protected non-conflicted Reserved will become conflicted under a foreign read, + // and is hence not idempotent under it. + ReservedFrz { conflicted } if prot && !conflicted => IdempotentForeignAccess::None, + // Otherwise, foreign reads do not affect Reserved + ReservedFrz { .. } => IdempotentForeignAccess::Read, + // Famously, ReservedIM survives foreign writes. It is never protected. + ReservedIM if prot => unreachable!("Protected ReservedIM should not exist!"), + ReservedIM => IdempotentForeignAccess::Write, + // Active changes on any foreign access (becomes Frozen/Disabled). + Active => IdempotentForeignAccess::None, + // Frozen survives foreign reads, but not writes. + Frozen => IdempotentForeignAccess::Read, + // Disabled survives foreign reads and writes. It survives them + // even if protected, because a protected `Disabled` is not initialized + // and does therefore not trigger UB. + Disabled => IdempotentForeignAccess::Write, + } + } } /// This module controls how each permission individually reacts to an access. @@ -305,6 +328,13 @@ impl Permission { (Disabled, _) => false, } } + + /// Returns the strongest foreign action this node survives (without change), + /// where `prot` indicates if it is protected. + /// See `foreign_access_skipping` + pub fn strongest_idempotent_foreign_access(&self, prot: bool) -> IdempotentForeignAccess { + self.inner.strongest_idempotent_foreign_access(prot) + } } impl PermTransition { @@ -575,7 +605,7 @@ mod propagation_optimization_checks { impl Exhaustive for AccessRelatedness { fn exhaustive() -> Box> { use AccessRelatedness::*; - Box::new(vec![This, StrictChildAccess, AncestorAccess, DistantAccess].into_iter()) + Box::new(vec![This, StrictChildAccess, AncestorAccess, CousinAccess].into_iter()) } } @@ -634,6 +664,35 @@ mod propagation_optimization_checks { } } + #[test] + #[rustfmt::skip] + fn permission_sifa_is_correct() { + // Tests that `strongest_idempotent_foreign_access` is correct. See `foreign_access_skipping.rs`. + for perm in PermissionPriv::exhaustive() { + // Assert that adding a protector makes it less idempotent. + if perm.compatible_with_protector() { + assert!(perm.strongest_idempotent_foreign_access(true) <= perm.strongest_idempotent_foreign_access(false)); + } + for prot in bool::exhaustive() { + if prot { + precondition!(perm.compatible_with_protector()); + } + let access = perm.strongest_idempotent_foreign_access(prot); + // We now assert it is idempotent, and never causes UB. + // First, if the SIFA includes foreign reads, assert it is idempotent under foreign reads. + if access >= IdempotentForeignAccess::Read { + // We use `CousinAccess` here. We could also use `AncestorAccess`, since `transition::perform_access` treats these the same. + // The only place they are treated differently is in protector end accesses, but these are not handled here. + assert_eq!(perm, transition::perform_access(AccessKind::Read, AccessRelatedness::CousinAccess, perm, prot).unwrap()); + } + // Then, if the SIFA includes foreign writes, assert it is idempotent under foreign writes. + if access >= IdempotentForeignAccess::Write { + assert_eq!(perm, transition::perform_access(AccessKind::Write, AccessRelatedness::CousinAccess, perm, prot).unwrap()); + } + } + } + } + #[test] // Check that all transitions are consistent with the order on PermissionPriv, // i.e. Reserved -> Active -> Frozen -> Disabled diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs index a551b017dfc..6d4ec36f7b6 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs @@ -21,6 +21,7 @@ use crate::borrow_tracker::tree_borrows::Permission; use crate::borrow_tracker::tree_borrows::diagnostics::{ self, NodeDebugInfo, TbError, TransitionError, }; +use crate::borrow_tracker::tree_borrows::foreign_access_skipping::IdempotentForeignAccess; use crate::borrow_tracker::tree_borrows::perms::PermTransition; use crate::borrow_tracker::tree_borrows::unimap::{UniEntry, UniIndex, UniKeyMap, UniValMap}; use crate::borrow_tracker::{GlobalState, ProtectorKind}; @@ -45,28 +46,28 @@ pub(super) struct LocationState { initialized: bool, /// This pointer's current permission / future initial permission. permission: Permission, - /// Strongest foreign access whose effects have already been applied to - /// this node and all its children since the last child access. - /// This is `None` if the most recent access is a child access, - /// `Some(Write)` if at least one foreign write access has been applied - /// since the previous child access, and `Some(Read)` if at least one - /// foreign read and no foreign write have occurred since the last child access. - latest_foreign_access: Option, + /// See `foreign_access_skipping.rs`. + /// Stores an idempotent foreign access for this location and its children. + /// For correctness, this must not be too strong, and the recorded idempotent foreign access + /// of all children must be at least as strong as this. For performance, it should be as strong as possible. + idempotent_foreign_access: IdempotentForeignAccess, } impl LocationState { /// Constructs a new initial state. It has neither been accessed, nor been subjected /// to any foreign access yet. /// The permission is not allowed to be `Active`. - fn new_uninit(permission: Permission) -> Self { + /// `sifa` is the (strongest) idempotent foreign access, see `foreign_access_skipping.rs` + fn new_uninit(permission: Permission, sifa: IdempotentForeignAccess) -> Self { assert!(permission.is_initial() || permission.is_disabled()); - Self { permission, initialized: false, latest_foreign_access: None } + Self { permission, initialized: false, idempotent_foreign_access: sifa } } /// Constructs a new initial state. It has not yet been subjected /// to any foreign access. However, it is already marked as having been accessed. - fn new_init(permission: Permission) -> Self { - Self { permission, initialized: true, latest_foreign_access: None } + /// `sifa` is the (strongest) idempotent foreign access, see `foreign_access_skipping.rs` + fn new_init(permission: Permission, sifa: IdempotentForeignAccess) -> Self { + Self { permission, initialized: true, idempotent_foreign_access: sifa } } /// Check if the location has been initialized, i.e. if it has @@ -143,52 +144,21 @@ impl LocationState { } } - // Helper to optimize the tree traversal. - // The optimization here consists of observing thanks to the tests - // `foreign_read_is_noop_after_foreign_write` and `all_transitions_idempotent`, - // that there are actually just three possible sequences of events that can occur - // in between two child accesses that produce different results. - // - // Indeed, - // - applying any number of foreign read accesses is the same as applying - // exactly one foreign read, - // - applying any number of foreign read or write accesses is the same - // as applying exactly one foreign write. - // therefore the three sequences of events that can produce different - // outcomes are - // - an empty sequence (`self.latest_foreign_access = None`) - // - a nonempty read-only sequence (`self.latest_foreign_access = Some(Read)`) - // - a nonempty sequence with at least one write (`self.latest_foreign_access = Some(Write)`) - // - // This function not only determines if skipping the propagation right now - // is possible, it also updates the internal state to keep track of whether - // the propagation can be skipped next time. - // It is a performance loss not to call this function when a foreign access occurs. - // FIXME: This optimization is wrong, and is currently disabled (by ignoring the - // result returned here). Since we presumably want an optimization like this, - // we should add it back. See #3864 for more information. + /// Tree traversal optimizations. See `foreign_access_skipping.rs`. + /// This checks if such a foreign access can be skipped. fn skip_if_known_noop( &self, access_kind: AccessKind, rel_pos: AccessRelatedness, ) -> ContinueTraversal { if rel_pos.is_foreign() { - let new_access_noop = match (self.latest_foreign_access, access_kind) { - // Previously applied transition makes the new one a guaranteed - // noop in the two following cases: - // (1) justified by `foreign_read_is_noop_after_foreign_write` - (Some(AccessKind::Write), AccessKind::Read) => true, - // (2) justified by `all_transitions_idempotent` - (Some(old), new) if old == new => true, - // In all other cases there has been a recent enough - // child access that the effects of the new foreign access - // need to be applied to this subtree. - _ => false, - }; + let happening_now = IdempotentForeignAccess::from_foreign(access_kind); + let new_access_noop = + self.idempotent_foreign_access.can_skip_foreign_access(happening_now); if new_access_noop { - // Abort traversal if the new transition is indeed guaranteed + // Abort traversal if the new access is indeed guaranteed // to be noop. - // No need to update `self.latest_foreign_access`, + // No need to update `self.idempotent_foreign_access`, // the type of the current streak among nonempty read-only // or nonempty with at least one write has not changed. ContinueTraversal::SkipSelfAndChildren @@ -207,20 +177,17 @@ impl LocationState { } /// Records a new access, so that future access can potentially be skipped - /// by `skip_if_known_noop`. - /// The invariants for this function are closely coupled to the function above: - /// It MUST be called on child accesses, and on foreign accesses MUST be called - /// when `skip_if_know_noop` returns `Recurse`, and MUST NOT be called otherwise. - /// FIXME: This optimization is wrong, and is currently disabled (by ignoring the - /// result returned here). Since we presumably want an optimization like this, - /// we should add it back. See #3864 for more information. - #[allow(unused)] + /// by `skip_if_known_noop`. This must be called on child accesses, and otherwise + /// shoud be called on foreign accesses for increased performance. It should not be called + /// when `skip_if_known_noop` indicated skipping, since it then is a no-op. + /// See `foreign_access_skipping.rs` fn record_new_access(&mut self, access_kind: AccessKind, rel_pos: AccessRelatedness) { - if rel_pos.is_foreign() { - self.latest_foreign_access = Some(access_kind); - } else { - self.latest_foreign_access = None; - } + debug_assert!(matches!( + self.skip_if_known_noop(access_kind, rel_pos), + ContinueTraversal::Recurse + )); + self.idempotent_foreign_access + .record_new(IdempotentForeignAccess::from_acc_and_rel(access_kind, rel_pos)); } } @@ -277,6 +244,11 @@ pub(super) struct Node { /// It is only ever `Disabled` for a tree root, since the root is initialized to `Active` by /// its own separate mechanism. default_initial_perm: Permission, + /// The default initial (strongest) idempotent foreign access. + /// This participates in the invariant for `LocationState::idempotent_foreign_access` + /// in cases where there is no location state yet. See `foreign_access_skipping.rs`, + /// and `LocationState::idempotent_foreign_access` for more information + default_initial_idempotent_foreign_access: IdempotentForeignAccess, /// Some extra information useful only for debugging purposes pub debug_info: NodeDebugInfo, } @@ -430,7 +402,7 @@ where } self.stack.push(( child, - AccessRelatedness::DistantAccess, + AccessRelatedness::CousinAccess, RecursionState::BeforeChildren, )); } @@ -591,6 +563,8 @@ impl Tree { parent: None, children: SmallVec::default(), default_initial_perm: root_default_perm, + // The root may never be skipped, all accesses will be local. + default_initial_idempotent_foreign_access: IdempotentForeignAccess::None, debug_info, }); nodes @@ -601,7 +575,10 @@ impl Tree { // We also ensure that it is initialized, so that no `Active` but // not yet initialized nodes exist. Essentially, we pretend there // was a write that initialized these to `Active`. - perms.insert(root_idx, LocationState::new_init(Permission::new_active())); + perms.insert( + root_idx, + LocationState::new_init(Permission::new_active(), IdempotentForeignAccess::None), + ); RangeMap::new(size, perms) }; Self { root: root_idx, nodes, rperms, tag_mapping } @@ -617,29 +594,79 @@ impl<'tcx> Tree { default_initial_perm: Permission, reborrow_range: AllocRange, span: Span, + prot: bool, ) -> InterpResult<'tcx> { assert!(!self.tag_mapping.contains_key(&new_tag)); let idx = self.tag_mapping.insert(new_tag); let parent_idx = self.tag_mapping.get(&parent_tag).unwrap(); + let strongest_idempotent = default_initial_perm.strongest_idempotent_foreign_access(prot); // Create the node self.nodes.insert(idx, Node { tag: new_tag, parent: Some(parent_idx), children: SmallVec::default(), default_initial_perm, + default_initial_idempotent_foreign_access: strongest_idempotent, debug_info: NodeDebugInfo::new(new_tag, default_initial_perm, span), }); // Register new_tag as a child of parent_tag self.nodes.get_mut(parent_idx).unwrap().children.push(idx); // Initialize perms - let perm = LocationState::new_init(default_initial_perm); + let perm = LocationState::new_init(default_initial_perm, strongest_idempotent); for (_perms_range, perms) in self.rperms.iter_mut(reborrow_range.start, reborrow_range.size) { perms.insert(idx, perm); } + + // Inserting the new perms might have broken the SIFA invariant (see `foreign_access_skipping.rs`). + // We now weaken the recorded SIFA for our parents, until the invariant is restored. + // We could weaken them all to `LocalAccess`, but it is more efficient to compute the SIFA + // for the new permission statically, and use that. + self.update_last_accessed_after_retag(parent_idx, strongest_idempotent); + interp_ok(()) } + /// Restores the SIFA "children are stronger" invariant after a retag. + /// See `foreign_access_skipping` and `new_child`. + fn update_last_accessed_after_retag( + &mut self, + mut current: UniIndex, + strongest_allowed: IdempotentForeignAccess, + ) { + // We walk the tree upwards, until the invariant is restored + loop { + let current_node = self.nodes.get_mut(current).unwrap(); + // Call `ensure_no_stronger_than` on all SIFAs for this node: the per-location SIFA, as well + // as the default SIFA for not-yet-initialized locations. + // Record whether we did any change; if not, the invariant is restored and we can stop the traversal. + let mut any_change = false; + for (_, map) in self.rperms.iter_mut_all() { + // Check if this node has a state for this location (or range of locations). + if let Some(perm) = map.get_mut(current) { + // Update the per-location SIFA, recording if it changed. + any_change |= + perm.idempotent_foreign_access.ensure_no_stronger_than(strongest_allowed); + } + } + // Now update `default_initial_idempotent_foreign_access`, which stores the default SIFA for not-yet-initialized locations. + any_change |= current_node + .default_initial_idempotent_foreign_access + .ensure_no_stronger_than(strongest_allowed); + + if any_change { + let Some(next) = self.nodes.get(current).unwrap().parent else { + // We have arrived at the root. + break; + }; + current = next; + continue; + } else { + break; + } + } + } + /// Deallocation requires /// - a pointer that permits write accesses /// - the absence of Strong Protectors anywhere in the allocation @@ -731,13 +758,8 @@ impl<'tcx> Tree { let node_skipper = |access_kind: AccessKind, args: &NodeAppArgs<'_>| -> ContinueTraversal { let NodeAppArgs { node, perm, rel_pos } = args; - let old_state = perm - .get() - .copied() - .unwrap_or_else(|| LocationState::new_uninit(node.default_initial_perm)); - // FIXME: See #3684 - let _would_skip_if_not_for_fixme = old_state.skip_if_known_noop(access_kind, *rel_pos); - ContinueTraversal::Recurse + let old_state = perm.get().copied().unwrap_or_else(|| node.default_location_state()); + old_state.skip_if_known_noop(access_kind, *rel_pos) }; let node_app = |perms_range: Range, access_kind: AccessKind, @@ -746,10 +768,12 @@ impl<'tcx> Tree { -> Result<(), TransitionError> { let NodeAppArgs { node, mut perm, rel_pos } = args; - let old_state = perm.or_insert(LocationState::new_uninit(node.default_initial_perm)); + let old_state = perm.or_insert(node.default_location_state()); - // FIXME: See #3684 - // old_state.record_new_access(access_kind, rel_pos); + // Call this function now, which ensures it is only called when + // `skip_if_known_noop` returns `Recurse`, due to the contract of + // `traverse_this_parents_children_other`. + old_state.record_new_access(access_kind, rel_pos); let protected = global.borrow().protected_tags.contains_key(&node.tag); let transition = old_state.perform_access(access_kind, rel_pos, protected)?; @@ -976,6 +1000,15 @@ impl Tree { } } +impl Node { + pub fn default_location_state(&self) -> LocationState { + LocationState::new_uninit( + self.default_initial_perm, + self.default_initial_idempotent_foreign_access, + ) + } +} + impl VisitProvenance for Tree { fn visit_provenance(&self, visit: &mut VisitWith<'_>) { // To ensure that the root never gets removed, we visit it @@ -998,15 +1031,14 @@ pub enum AccessRelatedness { AncestorAccess, /// The accessed pointer is neither of the above. // It's a cousin/uncle/etc., something in a side branch. - // FIXME: find a better name ? - DistantAccess, + CousinAccess, } impl AccessRelatedness { /// Check that access is either Ancestor or Distant, i.e. not /// a transitive child (initial pointer included). pub fn is_foreign(self) -> bool { - matches!(self, AccessRelatedness::AncestorAccess | AccessRelatedness::DistantAccess) + matches!(self, AccessRelatedness::AncestorAccess | AccessRelatedness::CousinAccess) } /// Given the AccessRelatedness for the parent node, compute the AccessRelatedness @@ -1016,7 +1048,7 @@ impl AccessRelatedness { use AccessRelatedness::*; match self { AncestorAccess | This => AncestorAccess, - StrictChildAccess | DistantAccess => DistantAccess, + StrictChildAccess | CousinAccess => CousinAccess, } } } diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs index 5d51a72852c..a429940748c 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs @@ -10,7 +10,11 @@ impl Exhaustive for LocationState { fn exhaustive() -> Box> { // We keep `latest_foreign_access` at `None` as that's just a cache. Box::new(<(Permission, bool)>::exhaustive().map(|(permission, initialized)| { - Self { permission, initialized, latest_foreign_access: None } + Self { + permission, + initialized, + idempotent_foreign_access: IdempotentForeignAccess::default(), + } })) } } @@ -260,15 +264,15 @@ mod spurious_read { match xy_rel { RelPosXY::MutuallyForeign => match self { - PtrSelector::X => (This, DistantAccess), - PtrSelector::Y => (DistantAccess, This), - PtrSelector::Other => (DistantAccess, DistantAccess), + PtrSelector::X => (This, CousinAccess), + PtrSelector::Y => (CousinAccess, This), + PtrSelector::Other => (CousinAccess, CousinAccess), }, RelPosXY::XChildY => match self { PtrSelector::X => (This, StrictChildAccess), PtrSelector::Y => (AncestorAccess, This), - PtrSelector::Other => (DistantAccess, DistantAccess), + PtrSelector::Other => (CousinAccess, CousinAccess), }, } } @@ -598,13 +602,18 @@ mod spurious_read { let source = LocStateProtPair { xy_rel: RelPosXY::MutuallyForeign, x: LocStateProt { - state: LocationState::new_init(Permission::new_frozen()), + // For the tests, the strongest idempotent foreign access does not matter, so we use `Default::default` + state: LocationState::new_init( + Permission::new_frozen(), + IdempotentForeignAccess::default(), + ), prot: true, }, y: LocStateProt { - state: LocationState::new_uninit(Permission::new_reserved( - /* freeze */ true, /* protected */ true, - )), + state: LocationState::new_uninit( + Permission::new_reserved(/* freeze */ true, /* protected */ true), + IdempotentForeignAccess::default(), + ), prot: true, }, }; -- cgit 1.4.1-3-g733a5 From f613636ae87e7e973138c7cb3e850ec26f93c723 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 4 Dec 2024 16:01:31 +0000 Subject: Rename `core_pattern_type` and `core_pattern_types` lib feature gates to `pattern_type_macro` That's what the gates are actually gating, and the single char difference in naming was not helpful either --- library/core/src/lib.rs | 2 +- library/core/src/pat.rs | 2 +- library/std/src/lib.rs | 2 +- .../crates/ide-db/src/generated/lints.rs | 13 ++----------- tests/codegen/pattern_type_symbols.rs | 3 +-- .../bad_const_generics_args_on_const_param.rs | 2 +- tests/ui/type/pattern_types/bad_pat.rs | 3 +-- tests/ui/type/pattern_types/bad_pat.stderr | 6 +++--- tests/ui/type/pattern_types/const_generics.rs | 3 +-- tests/ui/type/pattern_types/derives.rs | 3 +-- tests/ui/type/pattern_types/derives.stderr | 2 +- .../type/pattern_types/feature-gate-pattern_types.rs | 10 +++++----- .../pattern_types/feature-gate-pattern_types.stderr | 20 ++++++++++---------- .../pattern_types/feature-gate-pattern_types2.rs | 2 +- tests/ui/type/pattern_types/missing-is.rs | 2 +- tests/ui/type/pattern_types/range_patterns.rs | 3 +-- tests/ui/type/pattern_types/range_patterns.stderr | 10 +++++----- .../pattern_types/range_patterns_inherent_impls.rs | 3 +-- .../range_patterns_inherent_impls.stderr | 4 ++-- .../type/pattern_types/range_patterns_trait_impls.rs | 3 +-- .../pattern_types/range_patterns_trait_impls2.rs | 3 +-- .../pattern_types/range_patterns_trait_impls2.stderr | 2 +- .../ui/type/pattern_types/range_patterns_unusable.rs | 3 +-- .../pattern_types/range_patterns_unusable.stderr | 2 +- .../pattern_types/range_patterns_unusable_math.rs | 3 +-- .../range_patterns_unusable_math.stderr | 2 +- tests/ui/type/pattern_types/range_patterns_usage.rs | 3 +-- tests/ui/type/pattern_types/unimplemented_pat.rs | 3 +-- tests/ui/type/pattern_types/unimplemented_pat.stderr | 4 ++-- tests/ui/unpretty/expanded-exhaustive.rs | 2 +- tests/ui/unpretty/expanded-exhaustive.stdout | 2 +- 31 files changed, 53 insertions(+), 74 deletions(-) (limited to 'src/tools') diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index ab9c33ee754..fde6887c5ab 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -345,7 +345,7 @@ pub mod net; pub mod option; pub mod panic; pub mod panicking; -#[unstable(feature = "core_pattern_types", issue = "123646")] +#[unstable(feature = "pattern_type_macro", issue = "123646")] pub mod pat; pub mod pin; #[unstable(feature = "random", issue = "130703")] diff --git a/library/core/src/pat.rs b/library/core/src/pat.rs index 1f89d960be6..752e79c2dac 100644 --- a/library/core/src/pat.rs +++ b/library/core/src/pat.rs @@ -6,7 +6,7 @@ /// ``` #[macro_export] #[rustc_builtin_macro(pattern_type)] -#[unstable(feature = "core_pattern_type", issue = "123646")] +#[unstable(feature = "pattern_type_macro", issue = "123646")] macro_rules! pattern_type { ($($arg:tt)*) => { /* compiler built-in */ diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 585946c1d50..6be27b283b2 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -589,7 +589,7 @@ pub mod net; pub mod num; pub mod os; pub mod panic; -#[unstable(feature = "core_pattern_types", issue = "123646")] +#[unstable(feature = "pattern_type_macro", issue = "123646")] pub mod pat; pub mod path; #[unstable(feature = "anonymous_pipe", issue = "127154")] diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs index 266109765ab..b97dfb3b8ef 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs @@ -3936,17 +3936,8 @@ The tracking issue for this feature is: [#117693] "##, }, Lint { - label: "core_pattern_type", - description: r##"# `core_pattern_type` - -This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. - ------------------------- -"##, - }, - Lint { - label: "core_pattern_types", - description: r##"# `core_pattern_types` + label: "pattern_type_macro", + description: r##"# `pattern_type_macro` This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. diff --git a/tests/codegen/pattern_type_symbols.rs b/tests/codegen/pattern_type_symbols.rs index a99b3efca41..b504a3508f9 100644 --- a/tests/codegen/pattern_type_symbols.rs +++ b/tests/codegen/pattern_type_symbols.rs @@ -4,8 +4,7 @@ //@ compile-flags: -Csymbol-mangling-version=v0 -Copt-level=0 --crate-type=lib #![feature(pattern_types)] -#![feature(core_pattern_types)] -#![feature(core_pattern_type)] +#![feature(pattern_type_macro)] use std::pat::pattern_type; diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs index 3defe0cb44d..55f45ade388 100644 --- a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs +++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs @@ -1,4 +1,4 @@ -#![feature(pattern_types, core_pattern_type)] +#![feature(pattern_types, pattern_type_macro)] #![allow(internal_features)] type Pat = diff --git a/tests/ui/type/pattern_types/bad_pat.rs b/tests/ui/type/pattern_types/bad_pat.rs index 8ad042eeba6..6cb2a0f1f8e 100644 --- a/tests/ui/type/pattern_types/bad_pat.rs +++ b/tests/ui/type/pattern_types/bad_pat.rs @@ -1,6 +1,5 @@ #![feature(pattern_types)] -#![feature(core_pattern_types)] -#![feature(core_pattern_type)] +#![feature(pattern_type_macro)] use std::pat::pattern_type; diff --git a/tests/ui/type/pattern_types/bad_pat.stderr b/tests/ui/type/pattern_types/bad_pat.stderr index f5cf7930c83..c857cc3c3ad 100644 --- a/tests/ui/type/pattern_types/bad_pat.stderr +++ b/tests/ui/type/pattern_types/bad_pat.stderr @@ -1,5 +1,5 @@ error[E0586]: inclusive range with no end - --> $DIR/bad_pat.rs:7:43 + --> $DIR/bad_pat.rs:6:43 | LL | type NonNullU32_2 = pattern_type!(u32 is 1..=); | ^^^ @@ -12,7 +12,7 @@ LL + type NonNullU32_2 = pattern_type!(u32 is 1..); | error[E0586]: inclusive range with no end - --> $DIR/bad_pat.rs:9:40 + --> $DIR/bad_pat.rs:8:40 | LL | type Positive2 = pattern_type!(i32 is 0..=); | ^^^ @@ -25,7 +25,7 @@ LL + type Positive2 = pattern_type!(i32 is 0..); | error: wildcard patterns are not permitted for pattern types - --> $DIR/bad_pat.rs:11:33 + --> $DIR/bad_pat.rs:10:33 | LL | type Wild = pattern_type!(() is _); | ^ diff --git a/tests/ui/type/pattern_types/const_generics.rs b/tests/ui/type/pattern_types/const_generics.rs index 5bc6fd54e0f..5cef0dc0305 100644 --- a/tests/ui/type/pattern_types/const_generics.rs +++ b/tests/ui/type/pattern_types/const_generics.rs @@ -1,8 +1,7 @@ //@ check-pass #![feature(pattern_types)] -#![feature(core_pattern_types)] -#![feature(core_pattern_type)] +#![feature(pattern_type_macro)] use std::pat::pattern_type; diff --git a/tests/ui/type/pattern_types/derives.rs b/tests/ui/type/pattern_types/derives.rs index b8b53e61102..3878c47554d 100644 --- a/tests/ui/type/pattern_types/derives.rs +++ b/tests/ui/type/pattern_types/derives.rs @@ -1,8 +1,7 @@ //! Check that pattern types don't implement traits of their base automatically #![feature(pattern_types)] -#![feature(core_pattern_types)] -#![feature(core_pattern_type)] +#![feature(pattern_type_macro)] use std::pat::pattern_type; diff --git a/tests/ui/type/pattern_types/derives.stderr b/tests/ui/type/pattern_types/derives.stderr index 1d4d3fc55c3..9d4baef621b 100644 --- a/tests/ui/type/pattern_types/derives.stderr +++ b/tests/ui/type/pattern_types/derives.stderr @@ -1,5 +1,5 @@ error[E0369]: binary operation `==` cannot be applied to type `(i32) is 0..=999999999` - --> $DIR/derives.rs:11:20 + --> $DIR/derives.rs:10:20 | LL | #[derive(Clone, Copy, PartialEq)] | --------- in this derive macro expansion diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types.rs b/tests/ui/type/pattern_types/feature-gate-pattern_types.rs index e638f3c6c40..b90ba478402 100644 --- a/tests/ui/type/pattern_types/feature-gate-pattern_types.rs +++ b/tests/ui/type/pattern_types/feature-gate-pattern_types.rs @@ -3,12 +3,12 @@ use std::pat::pattern_type; type NonNullU32 = pattern_type!(u32 is 1..); -//~^ use of unstable library feature `core_pattern_type` +//~^ use of unstable library feature `pattern_type_macro` type Percent = pattern_type!(u32 is 0..=100); -//~^ use of unstable library feature `core_pattern_type` +//~^ use of unstable library feature `pattern_type_macro` type Negative = pattern_type!(i32 is ..=0); -//~^ use of unstable library feature `core_pattern_type` +//~^ use of unstable library feature `pattern_type_macro` type Positive = pattern_type!(i32 is 0..); -//~^ use of unstable library feature `core_pattern_type` +//~^ use of unstable library feature `pattern_type_macro` type Always = pattern_type!(Option is Some(_)); -//~^ use of unstable library feature `core_pattern_type` +//~^ use of unstable library feature `pattern_type_macro` diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr b/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr index 6cbadf370a7..69239d68bdc 100644 --- a/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr +++ b/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr @@ -1,51 +1,51 @@ -error[E0658]: use of unstable library feature `core_pattern_type` +error[E0658]: use of unstable library feature `pattern_type_macro` --> $DIR/feature-gate-pattern_types.rs:5:19 | LL | type NonNullU32 = pattern_type!(u32 is 1..); | ^^^^^^^^^^^^ | = note: see issue #123646 for more information - = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable + = help: add `#![feature(pattern_type_macro)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature `core_pattern_type` +error[E0658]: use of unstable library feature `pattern_type_macro` --> $DIR/feature-gate-pattern_types.rs:7:16 | LL | type Percent = pattern_type!(u32 is 0..=100); | ^^^^^^^^^^^^ | = note: see issue #123646 for more information - = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable + = help: add `#![feature(pattern_type_macro)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature `core_pattern_type` +error[E0658]: use of unstable library feature `pattern_type_macro` --> $DIR/feature-gate-pattern_types.rs:9:17 | LL | type Negative = pattern_type!(i32 is ..=0); | ^^^^^^^^^^^^ | = note: see issue #123646 for more information - = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable + = help: add `#![feature(pattern_type_macro)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature `core_pattern_type` +error[E0658]: use of unstable library feature `pattern_type_macro` --> $DIR/feature-gate-pattern_types.rs:11:17 | LL | type Positive = pattern_type!(i32 is 0..); | ^^^^^^^^^^^^ | = note: see issue #123646 for more information - = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable + = help: add `#![feature(pattern_type_macro)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature `core_pattern_type` +error[E0658]: use of unstable library feature `pattern_type_macro` --> $DIR/feature-gate-pattern_types.rs:13:15 | LL | type Always = pattern_type!(Option is Some(_)); | ^^^^^^^^^^^^ | = note: see issue #123646 for more information - = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable + = help: add `#![feature(pattern_type_macro)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 5 previous errors diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types2.rs b/tests/ui/type/pattern_types/feature-gate-pattern_types2.rs index d7b3ea58e02..50c355c8de6 100644 --- a/tests/ui/type/pattern_types/feature-gate-pattern_types2.rs +++ b/tests/ui/type/pattern_types/feature-gate-pattern_types2.rs @@ -1,7 +1,7 @@ //@ compile-flags: -Zno-analysis //@ check-pass -#![feature(core_pattern_type)] +#![feature(pattern_type_macro)] use std::pat::pattern_type; diff --git a/tests/ui/type/pattern_types/missing-is.rs b/tests/ui/type/pattern_types/missing-is.rs index 2fbcc1908ef..564b41649d8 100644 --- a/tests/ui/type/pattern_types/missing-is.rs +++ b/tests/ui/type/pattern_types/missing-is.rs @@ -1,4 +1,4 @@ -#![feature(core_pattern_type, core_pattern_types)] +#![feature(pattern_type_macro)] use std::pat::pattern_type; diff --git a/tests/ui/type/pattern_types/range_patterns.rs b/tests/ui/type/pattern_types/range_patterns.rs index 9eddc8cab7f..7c25edb1c3f 100644 --- a/tests/ui/type/pattern_types/range_patterns.rs +++ b/tests/ui/type/pattern_types/range_patterns.rs @@ -1,6 +1,5 @@ #![feature(pattern_types, rustc_attrs)] -#![feature(core_pattern_type)] -#![feature(core_pattern_types)] +#![feature(pattern_type_macro)] #![allow(incomplete_features)] //@ normalize-stderr-test: "pref: Align\([1-8] bytes\)" -> "pref: $$SOME_ALIGN" diff --git a/tests/ui/type/pattern_types/range_patterns.stderr b/tests/ui/type/pattern_types/range_patterns.stderr index 7bd0d826cab..0eed7c2ce1c 100644 --- a/tests/ui/type/pattern_types/range_patterns.stderr +++ b/tests/ui/type/pattern_types/range_patterns.stderr @@ -37,7 +37,7 @@ error: layout_of(NonZero) = Layout { max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } - --> $DIR/range_patterns.rs:11:1 + --> $DIR/range_patterns.rs:10:1 | LL | type X = std::num::NonZeroU32; | ^^^^^^ @@ -74,7 +74,7 @@ error: layout_of((u32) is 1..=) = Layout { max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } - --> $DIR/range_patterns.rs:13:1 + --> $DIR/range_patterns.rs:12:1 | LL | type Y = pattern_type!(u32 is 1..); | ^^^^^^ @@ -182,7 +182,7 @@ error: layout_of(Option<(u32) is 1..=>) = Layout { max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } - --> $DIR/range_patterns.rs:15:1 + --> $DIR/range_patterns.rs:14:1 | LL | type Z = Option; | ^^^^^^ @@ -290,7 +290,7 @@ error: layout_of(Option>) = Layout { max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } - --> $DIR/range_patterns.rs:17:1 + --> $DIR/range_patterns.rs:16:1 | LL | type A = Option; | ^^^^^^ @@ -334,7 +334,7 @@ error: layout_of(NonZeroU32New) = Layout { max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } - --> $DIR/range_patterns.rs:19:1 + --> $DIR/range_patterns.rs:18:1 | LL | struct NonZeroU32New(pattern_type!(u32 is 1..)); | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/type/pattern_types/range_patterns_inherent_impls.rs b/tests/ui/type/pattern_types/range_patterns_inherent_impls.rs index 9653a744c41..fe8feda0934 100644 --- a/tests/ui/type/pattern_types/range_patterns_inherent_impls.rs +++ b/tests/ui/type/pattern_types/range_patterns_inherent_impls.rs @@ -1,6 +1,5 @@ #![feature(pattern_types, rustc_attrs)] -#![feature(core_pattern_type)] -#![feature(core_pattern_types)] +#![feature(pattern_type_macro)] #![allow(incomplete_features)] //! check that pattern types can have traits implemented for them if diff --git a/tests/ui/type/pattern_types/range_patterns_inherent_impls.stderr b/tests/ui/type/pattern_types/range_patterns_inherent_impls.stderr index 784ebb0c9f0..ed2e4c0bd5f 100644 --- a/tests/ui/type/pattern_types/range_patterns_inherent_impls.stderr +++ b/tests/ui/type/pattern_types/range_patterns_inherent_impls.stderr @@ -1,12 +1,12 @@ error[E0390]: cannot define inherent `impl` for primitive types outside of `core` - --> $DIR/range_patterns_inherent_impls.rs:13:1 + --> $DIR/range_patterns_inherent_impls.rs:12:1 | LL | impl Y { | ^^^^^^ | = help: consider moving this inherent impl into `core` if possible help: alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items - --> $DIR/range_patterns_inherent_impls.rs:15:5 + --> $DIR/range_patterns_inherent_impls.rs:14:5 | LL | fn foo() {} | ^^^^^^^^ diff --git a/tests/ui/type/pattern_types/range_patterns_trait_impls.rs b/tests/ui/type/pattern_types/range_patterns_trait_impls.rs index f8c9af86281..1731cd470fe 100644 --- a/tests/ui/type/pattern_types/range_patterns_trait_impls.rs +++ b/tests/ui/type/pattern_types/range_patterns_trait_impls.rs @@ -1,6 +1,5 @@ #![feature(pattern_types, rustc_attrs)] -#![feature(core_pattern_type)] -#![feature(core_pattern_types)] +#![feature(pattern_type_macro)] #![allow(incomplete_features)] //! check that pattern types can have local traits diff --git a/tests/ui/type/pattern_types/range_patterns_trait_impls2.rs b/tests/ui/type/pattern_types/range_patterns_trait_impls2.rs index acde4580c1b..90f80a2f346 100644 --- a/tests/ui/type/pattern_types/range_patterns_trait_impls2.rs +++ b/tests/ui/type/pattern_types/range_patterns_trait_impls2.rs @@ -1,6 +1,5 @@ #![feature(pattern_types, rustc_attrs)] -#![feature(core_pattern_type)] -#![feature(core_pattern_types)] +#![feature(pattern_type_macro)] #![allow(incomplete_features)] //! check that pattern types can have local traits diff --git a/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr b/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr index df56db031ed..d5c539b6c52 100644 --- a/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr +++ b/tests/ui/type/pattern_types/range_patterns_trait_impls2.stderr @@ -1,5 +1,5 @@ error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/range_patterns_trait_impls2.rs:13:1 + --> $DIR/range_patterns_trait_impls2.rs:12:1 | LL | impl Eq for Y {} | ^^^^^^^^^^^^- diff --git a/tests/ui/type/pattern_types/range_patterns_unusable.rs b/tests/ui/type/pattern_types/range_patterns_unusable.rs index 7cde44f4133..98f13ca0bc0 100644 --- a/tests/ui/type/pattern_types/range_patterns_unusable.rs +++ b/tests/ui/type/pattern_types/range_patterns_unusable.rs @@ -1,6 +1,5 @@ #![feature(pattern_types, rustc_attrs)] -#![feature(core_pattern_type)] -#![feature(core_pattern_types)] +#![feature(pattern_type_macro)] #![allow(incomplete_features)] //! Some practical niche checks. diff --git a/tests/ui/type/pattern_types/range_patterns_unusable.stderr b/tests/ui/type/pattern_types/range_patterns_unusable.stderr index aa0e592684b..8377d417452 100644 --- a/tests/ui/type/pattern_types/range_patterns_unusable.stderr +++ b/tests/ui/type/pattern_types/range_patterns_unusable.stderr @@ -1,5 +1,5 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/range_patterns_unusable.rs:14:35 + --> $DIR/range_patterns_unusable.rs:13:35 | LL | let _: Option = unsafe { std::mem::transmute(z) }; | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/type/pattern_types/range_patterns_unusable_math.rs b/tests/ui/type/pattern_types/range_patterns_unusable_math.rs index bc1ab75429d..ece4009e1e7 100644 --- a/tests/ui/type/pattern_types/range_patterns_unusable_math.rs +++ b/tests/ui/type/pattern_types/range_patterns_unusable_math.rs @@ -1,6 +1,5 @@ #![feature(pattern_types, rustc_attrs)] -#![feature(core_pattern_type)] -#![feature(core_pattern_types)] +#![feature(pattern_type_macro)] #![allow(incomplete_features)] //! check that pattern types don't have an `Add` impl. diff --git a/tests/ui/type/pattern_types/range_patterns_unusable_math.stderr b/tests/ui/type/pattern_types/range_patterns_unusable_math.stderr index e52d899a703..373615e3714 100644 --- a/tests/ui/type/pattern_types/range_patterns_unusable_math.stderr +++ b/tests/ui/type/pattern_types/range_patterns_unusable_math.stderr @@ -1,5 +1,5 @@ error[E0369]: cannot add `u32` to `(u32) is 1..=` - --> $DIR/range_patterns_unusable_math.rs:15:15 + --> $DIR/range_patterns_unusable_math.rs:14:15 | LL | let x = x + 1_u32; | - ^ ----- u32 diff --git a/tests/ui/type/pattern_types/range_patterns_usage.rs b/tests/ui/type/pattern_types/range_patterns_usage.rs index 2a9f736ae61..0ecbdcaa0f7 100644 --- a/tests/ui/type/pattern_types/range_patterns_usage.rs +++ b/tests/ui/type/pattern_types/range_patterns_usage.rs @@ -1,6 +1,5 @@ #![feature(pattern_types, rustc_attrs)] -#![feature(core_pattern_type)] -#![feature(core_pattern_types)] +#![feature(pattern_type_macro)] #![allow(incomplete_features)] //@ check-pass diff --git a/tests/ui/type/pattern_types/unimplemented_pat.rs b/tests/ui/type/pattern_types/unimplemented_pat.rs index c02160ff58a..b2398cec7c9 100644 --- a/tests/ui/type/pattern_types/unimplemented_pat.rs +++ b/tests/ui/type/pattern_types/unimplemented_pat.rs @@ -1,8 +1,7 @@ //! This test ensures we do not ICE for unimplemented //! patterns unless the feature gate is enabled. -#![feature(core_pattern_type)] -#![feature(core_pattern_types)] +#![feature(pattern_type_macro)] use std::pat::pattern_type; diff --git a/tests/ui/type/pattern_types/unimplemented_pat.stderr b/tests/ui/type/pattern_types/unimplemented_pat.stderr index 481c6017dcc..7b0f9cbaa6a 100644 --- a/tests/ui/type/pattern_types/unimplemented_pat.stderr +++ b/tests/ui/type/pattern_types/unimplemented_pat.stderr @@ -1,5 +1,5 @@ error[E0658]: pattern types are unstable - --> $DIR/unimplemented_pat.rs:9:15 + --> $DIR/unimplemented_pat.rs:8:15 | LL | type Always = pattern_type!(Option is Some(_)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | type Always = pattern_type!(Option is Some(_)); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: pattern types are unstable - --> $DIR/unimplemented_pat.rs:12:16 + --> $DIR/unimplemented_pat.rs:11:16 | LL | type Binding = pattern_type!(Option is x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs index 891021e8766..9af57fe4c3c 100644 --- a/tests/ui/unpretty/expanded-exhaustive.rs +++ b/tests/ui/unpretty/expanded-exhaustive.rs @@ -8,7 +8,6 @@ #![feature(builtin_syntax)] #![feature(concat_idents)] #![feature(const_trait_impl)] -#![feature(core_pattern_type)] #![feature(decl_macro)] #![feature(deref_patterns)] #![feature(explicit_tail_calls)] @@ -18,6 +17,7 @@ #![feature(never_patterns)] #![feature(never_type)] #![feature(pattern_types)] +#![feature(pattern_type_macro)] #![feature(prelude_import)] #![feature(specialization)] #![feature(trace_macros)] diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout index 007626e2c44..14a274415ca 100644 --- a/tests/ui/unpretty/expanded-exhaustive.stdout +++ b/tests/ui/unpretty/expanded-exhaustive.stdout @@ -9,7 +9,6 @@ #![feature(builtin_syntax)] #![feature(concat_idents)] #![feature(const_trait_impl)] -#![feature(core_pattern_type)] #![feature(decl_macro)] #![feature(deref_patterns)] #![feature(explicit_tail_calls)] @@ -19,6 +18,7 @@ #![feature(never_patterns)] #![feature(never_type)] #![feature(pattern_types)] +#![feature(pattern_type_macro)] #![feature(prelude_import)] #![feature(specialization)] #![feature(trace_macros)] -- cgit 1.4.1-3-g733a5 From c0f00086f85ae1fff34dd2daf6a11850e5bfc2f0 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Wed, 20 Nov 2024 03:00:58 +0000 Subject: Tweak ptr in pattern error Conform to error style guide. --- compiler/rustc_mir_build/messages.ftl | 4 +- compiler/rustc_mir_build/src/errors.rs | 2 + src/tools/tidy/src/fluent_period.rs | 1 - .../issue-34784-match-on-non-int-raw-ptr.stderr | 24 ++++++--- .../ui/consts/const_in_pattern/issue-44333.stderr | 12 +++-- tests/ui/pattern/usefulness/consts-opaque.stderr | 48 +++++++++++------ .../fn-ptr-is-not-structurally-matchable.stderr | 60 ++++++++++++++-------- .../issue-63479-match-fnptr.stderr | 12 +++-- 8 files changed, 109 insertions(+), 54 deletions(-) (limited to 'src/tools') diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index ad2f13f6d21..2bf49137e8f 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -274,7 +274,9 @@ mir_build_non_partial_eq_match = mir_build_pattern_not_covered = refutable pattern in {$origin} .pattern_ty = the matched value is of type `{$pattern_ty}` -mir_build_pointer_pattern = function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +mir_build_pointer_pattern = function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon + .label = can't be used in patterns + .note = see https://github.com/rust-lang/rust/issues/70861 for details mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 226c469b7d7..7f4bb139fad 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -916,8 +916,10 @@ pub(crate) struct NaNPattern { #[derive(Diagnostic)] #[diag(mir_build_pointer_pattern)] +#[note] pub(crate) struct PointerPattern { #[primary_span] + #[label] pub(crate) span: Span, } diff --git a/src/tools/tidy/src/fluent_period.rs b/src/tools/tidy/src/fluent_period.rs index 8bc404dc858..6a136e5aec6 100644 --- a/src/tools/tidy/src/fluent_period.rs +++ b/src/tools/tidy/src/fluent_period.rs @@ -18,7 +18,6 @@ const ALLOWLIST: &[&str] = &[ "const_eval_validation_failure_note", "driver_impl_ice", "incremental_corrupt_file", - "mir_build_pointer_pattern", ]; fn check_period(filename: &str, contents: &str, bad: &mut bool) { diff --git a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr index cc7ec771e6c..0453a88e43d 100644 --- a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr +++ b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr @@ -1,38 +1,46 @@ -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:9:9 | LL | const C: *const u8 = &0; | ------------------ constant defined here ... LL | C => {} - | ^ + | ^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:16:9 | LL | const C_INNER: (*const u8, u8) = (C, 0); | ------------------------------ constant defined here ... LL | C_INNER => {} - | ^^^^^^^ + | ^^^^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:27:9 | LL | const D: *const [u8; 4] = b"abcd"; | ----------------------- constant defined here ... LL | D => {} - | ^ + | ^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:32:9 | LL | const STR: *const str = "abcd"; | --------------------- constant defined here ... LL | STR => {} - | ^^^ + | ^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details error: aborting due to 4 previous errors diff --git a/tests/ui/consts/const_in_pattern/issue-44333.stderr b/tests/ui/consts/const_in_pattern/issue-44333.stderr index 81393952f0f..61b45377c76 100644 --- a/tests/ui/consts/const_in_pattern/issue-44333.stderr +++ b/tests/ui/consts/const_in_pattern/issue-44333.stderr @@ -1,20 +1,24 @@ -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/issue-44333.rs:15:9 | LL | const FOO: Func = foo; | --------------- constant defined here ... LL | FOO => println!("foo"), - | ^^^ + | ^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/issue-44333.rs:16:9 | LL | const BAR: Func = bar; | --------------- constant defined here ... LL | BAR => println!("bar"), - | ^^^ + | ^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details error: aborting due to 2 previous errors diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr index 15aa1769662..d52451d9438 100644 --- a/tests/ui/pattern/usefulness/consts-opaque.stderr +++ b/tests/ui/pattern/usefulness/consts-opaque.stderr @@ -1,74 +1,90 @@ -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/consts-opaque.rs:96:9 | LL | const QUUX: Quux = quux; | ---------------- constant defined here ... LL | QUUX => {} - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/consts-opaque.rs:97:9 | LL | const QUUX: Quux = quux; | ---------------- constant defined here ... LL | QUUX => {} - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/consts-opaque.rs:106:9 | LL | const WRAPQUUX: Wrap = Wrap(quux); | -------------------------- constant defined here ... LL | WRAPQUUX => {} - | ^^^^^^^^ + | ^^^^^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/consts-opaque.rs:107:9 | LL | const WRAPQUUX: Wrap = Wrap(quux); | -------------------------- constant defined here ... LL | WRAPQUUX => {} - | ^^^^^^^^ + | ^^^^^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/consts-opaque.rs:113:9 | LL | const WRAPQUUX: Wrap = Wrap(quux); | -------------------------- constant defined here ... LL | WRAPQUUX => {} - | ^^^^^^^^ + | ^^^^^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/consts-opaque.rs:121:9 | LL | const WRAPQUUX: Wrap = Wrap(quux); | -------------------------- constant defined here ... LL | WRAPQUUX => {} - | ^^^^^^^^ + | ^^^^^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/consts-opaque.rs:132:9 | LL | const WHOKNOWSQUUX: WhoKnows = WhoKnows::Yay(quux); | ---------------------------------- constant defined here ... LL | WHOKNOWSQUUX => {} - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/consts-opaque.rs:134:9 | LL | const WHOKNOWSQUUX: WhoKnows = WhoKnows::Yay(quux); | ---------------------------------- constant defined here ... LL | WHOKNOWSQUUX => {} - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details error: unreachable pattern --> $DIR/consts-opaque.rs:48:9 diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-not-structurally-matchable.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-not-structurally-matchable.stderr index ee6f44a364d..cdbe72ca48f 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-not-structurally-matchable.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-not-structurally-matchable.stderr @@ -1,92 +1,112 @@ -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/fn-ptr-is-not-structurally-matchable.rs:41:14 | LL | const CFN1: Wrap = Wrap(trivial); | ---------------------- constant defined here ... LL | Wrap(CFN1) => count += 1, - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/fn-ptr-is-not-structurally-matchable.rs:49:14 | LL | const CFN2: Wrap = Wrap(sm_to); | ------------------------ constant defined here ... LL | Wrap(CFN2) => count += 1, - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/fn-ptr-is-not-structurally-matchable.rs:57:14 | LL | const CFN3: Wrap SM> = Wrap(to_sm); | ---------------------------- constant defined here ... LL | Wrap(CFN3) => count += 1, - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/fn-ptr-is-not-structurally-matchable.rs:65:14 | LL | const CFN4: Wrap = Wrap(not_sm_to); | --------------------------- constant defined here ... LL | Wrap(CFN4) => count += 1, - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/fn-ptr-is-not-structurally-matchable.rs:73:14 | LL | const CFN5: Wrap NotSM> = Wrap(to_not_sm); | ------------------------------- constant defined here ... LL | Wrap(CFN5) => count += 1, - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/fn-ptr-is-not-structurally-matchable.rs:81:14 | LL | const CFN6: Wrap = Wrap(r_sm_to); | ------------------------- constant defined here ... LL | Wrap(CFN6) => count += 1, - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/fn-ptr-is-not-structurally-matchable.rs:89:14 | LL | const CFN7: Wrap &SM> = Wrap(r_to_r_sm); | -------------------------------- constant defined here ... LL | Wrap(CFN7) => count += 1, - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/fn-ptr-is-not-structurally-matchable.rs:97:14 | LL | const CFN8: Wrap = Wrap(r_not_sm_to); | ---------------------------- constant defined here ... LL | Wrap(CFN8) => count += 1, - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/fn-ptr-is-not-structurally-matchable.rs:105:14 | LL | const CFN9: Wrap &NotSM> = Wrap(r_to_r_not_sm); | ----------------------------------- constant defined here ... LL | Wrap(CFN9) => count += 1, - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/fn-ptr-is-not-structurally-matchable.rs:127:9 | LL | const CFOO: Foo = Foo { | --------------- constant defined here ... LL | CFOO => count += 1, - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details error: aborting due to 10 previous errors diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr index be735ccab0a..ea6121839be 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr @@ -1,20 +1,24 @@ -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/issue-63479-match-fnptr.rs:32:7 | LL | const TEST: Fn = my_fn; | -------------- constant defined here ... LL | B(TEST) => println!("matched"), - | ^^^^ + | ^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details -error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon --> $DIR/issue-63479-match-fnptr.rs:37:5 | LL | const TEST2: (Fn, u8) = (TEST, 0); | --------------------- constant defined here ... LL | TEST2 => println!("matched"), - | ^^^^^ + | ^^^^^ can't be used in patterns + | + = note: see https://github.com/rust-lang/rust/issues/70861 for details error: aborting due to 2 previous errors -- cgit 1.4.1-3-g733a5 From 0b737a163eb47e9eb6e6c461159764758722e6f9 Mon Sep 17 00:00:00 2001 From: Jakub Beránek Date: Wed, 4 Dec 2024 23:01:58 +0100 Subject: Exclude additional subtrees in `ruff` config --- src/tools/tidy/config/ruff.toml | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/tools') diff --git a/src/tools/tidy/config/ruff.toml b/src/tools/tidy/config/ruff.toml index de23d93593c..4a5aa618be1 100644 --- a/src/tools/tidy/config/ruff.toml +++ b/src/tools/tidy/config/ruff.toml @@ -19,6 +19,9 @@ extend-exclude = [ "src/tools/enzyme/", "src/tools/rustc-perf/", "src/gcc/", + "compiler/rustc_codegen_gcc", + "src/tools/clippy", + "src/tools/miri", # Hack: CI runs from a subdirectory under the main checkout "../src/doc/nomicon/", "../src/tools/cargo/", @@ -34,6 +37,9 @@ extend-exclude = [ "../src/tools/enzyme/", "../src/tools/rustc-perf/", "../src/gcc/", + "../compiler/rustc_codegen_gcc", + "../src/tools/clippy", + "../src/tools/miri", ] [lint] -- cgit 1.4.1-3-g733a5 From 536516f949ff37b0e10eaed835c2d3592d03e576 Mon Sep 17 00:00:00 2001 From: Jakub Beránek Date: Wed, 4 Dec 2024 23:02:25 +0100 Subject: Reformat Python code with `ruff` --- library/core/src/unicode/printable.py | 53 +- src/bootstrap/bootstrap.py | 663 ++++++++++++--------- src/bootstrap/bootstrap_test.py | 42 +- src/bootstrap/configure.py | 519 ++++++++++------ src/ci/cpu-usage-over-time.py | 36 +- .../host-x86_64/test-various/uefi_qemu_test/run.py | 149 ++--- src/ci/docker/scripts/android-sdk-manager.py | 60 +- src/ci/docker/scripts/fuchsia-test-runner.py | 8 +- src/ci/github-actions/calculate-job-matrix.py | 13 +- src/ci/scripts/upload-build-metrics.py | 21 +- src/etc/dec2flt_table.py | 46 +- src/etc/gdb_load_rust_pretty_printers.py | 1 + src/etc/gdb_lookup.py | 7 +- src/etc/gdb_providers.py | 35 +- src/etc/generate-deriving-span-tests.py | 62 +- src/etc/generate-keyword-tests.py | 8 +- src/etc/htmldocck.py | 260 ++++---- src/etc/lldb_batchmode.py | 69 ++- src/etc/lldb_providers.py | 186 ++++-- src/etc/rust_types.py | 3 +- src/tools/publish_toolstate.py | 226 +++---- .../dependency-with-embedded-visualizers.py | 3 + tests/debuginfo/embedded-visualizer-point.py | 3 + tests/debuginfo/embedded-visualizer.py | 3 + x.py | 9 +- 25 files changed, 1541 insertions(+), 944 deletions(-) (limited to 'src/tools') diff --git a/library/core/src/unicode/printable.py b/library/core/src/unicode/printable.py index 4d39ace066c..260fa9f9e6a 100755 --- a/library/core/src/unicode/printable.py +++ b/library/core/src/unicode/printable.py @@ -9,7 +9,8 @@ import csv import os import subprocess -NUM_CODEPOINTS=0x110000 +NUM_CODEPOINTS = 0x110000 + def to_ranges(iter): current = None @@ -23,11 +24,15 @@ def to_ranges(iter): if current is not None: yield tuple(current) + def get_escaped(codepoints): for c in codepoints: - if (c.class_ or "Cn") in "Cc Cf Cs Co Cn Zl Zp Zs".split() and c.value != ord(' '): + if (c.class_ or "Cn") in "Cc Cf Cs Co Cn Zl Zp Zs".split() and c.value != ord( + " " + ): yield c.value + def get_file(f): try: return open(os.path.basename(f)) @@ -35,7 +40,9 @@ def get_file(f): subprocess.run(["curl", "-O", f], check=True) return open(os.path.basename(f)) -Codepoint = namedtuple('Codepoint', 'value class_') + +Codepoint = namedtuple("Codepoint", "value class_") + def get_codepoints(f): r = csv.reader(f, delimiter=";") @@ -66,13 +73,14 @@ def get_codepoints(f): for c in range(prev_codepoint + 1, NUM_CODEPOINTS): yield Codepoint(c, None) + def compress_singletons(singletons): - uppers = [] # (upper, # items in lowers) + uppers = [] # (upper, # items in lowers) lowers = [] for i in singletons: upper = i >> 8 - lower = i & 0xff + lower = i & 0xFF if len(uppers) == 0 or uppers[-1][0] != upper: uppers.append((upper, 1)) else: @@ -82,10 +90,11 @@ def compress_singletons(singletons): return uppers, lowers + def compress_normal(normal): # lengths 0x00..0x7f are encoded as 00, 01, ..., 7e, 7f # lengths 0x80..0x7fff are encoded as 80 80, 80 81, ..., ff fe, ff ff - compressed = [] # [truelen, (truelenaux), falselen, (falselenaux)] + compressed = [] # [truelen, (truelenaux), falselen, (falselenaux)] prev_start = 0 for start, count in normal: @@ -95,21 +104,22 @@ def compress_normal(normal): assert truelen < 0x8000 and falselen < 0x8000 entry = [] - if truelen > 0x7f: + if truelen > 0x7F: entry.append(0x80 | (truelen >> 8)) - entry.append(truelen & 0xff) + entry.append(truelen & 0xFF) else: - entry.append(truelen & 0x7f) - if falselen > 0x7f: + entry.append(truelen & 0x7F) + if falselen > 0x7F: entry.append(0x80 | (falselen >> 8)) - entry.append(falselen & 0xff) + entry.append(falselen & 0xFF) else: - entry.append(falselen & 0x7f) + entry.append(falselen & 0x7F) compressed.append(entry) return compressed + def print_singletons(uppers, lowers, uppersname, lowersname): print("#[rustfmt::skip]") print("const {}: &[(u8, u8)] = &[".format(uppersname)) @@ -119,9 +129,12 @@ def print_singletons(uppers, lowers, uppersname, lowersname): print("#[rustfmt::skip]") print("const {}: &[u8] = &[".format(lowersname)) for i in range(0, len(lowers), 8): - print(" {}".format(" ".join("{:#04x},".format(x) for x in lowers[i:i+8]))) + print( + " {}".format(" ".join("{:#04x},".format(x) for x in lowers[i : i + 8])) + ) print("];") + def print_normal(normal, normalname): print("#[rustfmt::skip]") print("const {}: &[u8] = &[".format(normalname)) @@ -129,12 +142,13 @@ def print_normal(normal, normalname): print(" {}".format(" ".join("{:#04x},".format(i) for i in v))) print("];") + def main(): file = get_file("https://www.unicode.org/Public/UNIDATA/UnicodeData.txt") codepoints = get_codepoints(file) - CUTOFF=0x10000 + CUTOFF = 0x10000 singletons0 = [] singletons1 = [] normal0 = [] @@ -234,10 +248,11 @@ pub(crate) fn is_printable(x: char) -> bool { }\ """) print() - print_singletons(singletons0u, singletons0l, 'SINGLETONS0U', 'SINGLETONS0L') - print_singletons(singletons1u, singletons1l, 'SINGLETONS1U', 'SINGLETONS1L') - print_normal(normal0, 'NORMAL0') - print_normal(normal1, 'NORMAL1') + print_singletons(singletons0u, singletons0l, "SINGLETONS0U", "SINGLETONS0L") + print_singletons(singletons1u, singletons1l, "SINGLETONS1U", "SINGLETONS1L") + print_normal(normal0, "NORMAL0") + print_normal(normal1, "NORMAL1") + -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 762f4e653e9..95aa2e992dd 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -19,14 +19,17 @@ try: except ImportError: lzma = None + def platform_is_win32(): - return sys.platform == 'win32' + return sys.platform == "win32" + if platform_is_win32(): EXE_SUFFIX = ".exe" else: EXE_SUFFIX = "" + def get_cpus(): if hasattr(os, "sched_getaffinity"): return len(os.sched_getaffinity(0)) @@ -51,11 +54,14 @@ def get(base, url, path, checksums, verbose=False): try: if url not in checksums: - raise RuntimeError(("src/stage0 doesn't contain a checksum for {}. " - "Pre-built artifacts might not be available for this " - "target at this time, see https://doc.rust-lang.org/nightly" - "/rustc/platform-support.html for more information.") - .format(url)) + raise RuntimeError( + ( + "src/stage0 doesn't contain a checksum for {}. " + "Pre-built artifacts might not be available for this " + "target at this time, see https://doc.rust-lang.org/nightly" + "/rustc/platform-support.html for more information." + ).format(url) + ) sha256 = checksums[url] if os.path.exists(path): if verify(path, sha256, False): @@ -64,8 +70,11 @@ def get(base, url, path, checksums, verbose=False): return else: if verbose: - eprint("ignoring already-download file", - path, "due to failed verification") + eprint( + "ignoring already-download file", + path, + "due to failed verification", + ) os.unlink(path) download(temp_path, "{}/{}".format(base, url), True, verbose) if not verify(temp_path, sha256, verbose): @@ -79,12 +88,14 @@ def get(base, url, path, checksums, verbose=False): eprint("removing", temp_path) os.unlink(temp_path) + def curl_version(): m = re.match(bytes("^curl ([0-9]+)\\.([0-9]+)", "utf8"), require(["curl", "-V"])) if m is None: return (0, 0) return (int(m[1]), int(m[2])) + def download(path, url, probably_big, verbose): for _ in range(4): try: @@ -114,32 +125,53 @@ def _download(path, url, probably_big, verbose, exception): require(["curl", "--version"], exception=platform_is_win32()) extra_flags = [] if curl_version() > (7, 70): - extra_flags = [ "--retry-all-errors" ] + extra_flags = ["--retry-all-errors"] # options should be kept in sync with # src/bootstrap/src/core/download.rs # for consistency. # they are also more compreprensivly explained in that file. - run(["curl", option] + extra_flags + [ - # Follow redirect. - "--location", - # timeout if speed is < 10 bytes/sec for > 30 seconds - "--speed-time", "30", "--speed-limit", "10", - # timeout if cannot connect within 30 seconds - "--connect-timeout", "30", - "--output", path, - "--continue-at", "-", - "--retry", "3", "--show-error", "--remote-time", "--fail", url], + run( + ["curl", option] + + extra_flags + + [ + # Follow redirect. + "--location", + # timeout if speed is < 10 bytes/sec for > 30 seconds + "--speed-time", + "30", + "--speed-limit", + "10", + # timeout if cannot connect within 30 seconds + "--connect-timeout", + "30", + "--output", + path, + "--continue-at", + "-", + "--retry", + "3", + "--show-error", + "--remote-time", + "--fail", + url, + ], verbose=verbose, - exception=True, # Will raise RuntimeError on failure + exception=True, # Will raise RuntimeError on failure ) except (subprocess.CalledProcessError, OSError, RuntimeError): # see http://serverfault.com/questions/301128/how-to-download + script = "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;" if platform_is_win32(): - run_powershell([ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;", - "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')".format(url, path)], + run_powershell( + [ + script, + "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')".format( + url, path + ), + ], verbose=verbose, - exception=exception) + exception=exception, + ) # Check if the RuntimeError raised by run(curl) should be silenced elif verbose or exception: raise @@ -153,9 +185,11 @@ def verify(path, expected, verbose): found = hashlib.sha256(source.read()).hexdigest() verified = found == expected if not verified: - eprint("invalid checksum:\n" - " found: {}\n" - " expected: {}".format(found, expected)) + eprint( + "invalid checksum:\n" " found: {}\n" " expected: {}".format( + found, expected + ) + ) return verified @@ -170,7 +204,7 @@ def unpack(tarball, tarball_suffix, dst, verbose=False, match=None): name = member.replace(fname + "/", "", 1) if match is not None and not name.startswith(match): continue - name = name[len(match) + 1:] + name = name[len(match) + 1 :] dst_path = os.path.join(dst, name) if verbose: @@ -186,18 +220,18 @@ def unpack(tarball, tarball_suffix, dst, verbose=False, match=None): def run(args, verbose=False, exception=False, is_bootstrap=False, **kwargs): """Run a child program in a new process""" if verbose: - eprint("running: " + ' '.join(args)) + eprint("running: " + " ".join(args)) sys.stdout.flush() # Ensure that the .exe is used on Windows just in case a Linux ELF has been # compiled in the same directory. - if os.name == 'nt' and not args[0].endswith('.exe'): - args[0] += '.exe' + if os.name == "nt" and not args[0].endswith(".exe"): + args[0] += ".exe" # Use Popen here instead of call() as it apparently allows powershell on # Windows to not lock up waiting for input presumably. ret = subprocess.Popen(args, **kwargs) code = ret.wait() if code != 0: - err = "failed to run: " + ' '.join(args) + err = "failed to run: " + " ".join(args) if verbose or exception: raise RuntimeError(err) # For most failures, we definitely do want to print this error, or the user will have no @@ -209,30 +243,30 @@ def run(args, verbose=False, exception=False, is_bootstrap=False, **kwargs): else: sys.exit(err) + def run_powershell(script, *args, **kwargs): """Run a powershell script""" run(["PowerShell.exe", "/nologo", "-Command"] + script, *args, **kwargs) def require(cmd, exit=True, exception=False): - '''Run a command, returning its output. + """Run a command, returning its output. On error, If `exception` is `True`, raise the error Otherwise If `exit` is `True`, exit the process - Else return None.''' + Else return None.""" try: return subprocess.check_output(cmd).strip() except (subprocess.CalledProcessError, OSError) as exc: if exception: raise elif exit: - eprint("ERROR: unable to run `{}`: {}".format(' '.join(cmd), exc)) + eprint("ERROR: unable to run `{}`: {}".format(" ".join(cmd), exc)) eprint("Please make sure it's installed and in the path.") sys.exit(1) return None - def format_build_time(duration): """Return a nicer format for build time @@ -252,13 +286,16 @@ def default_build_triple(verbose): if platform_is_win32(): try: - version = subprocess.check_output(["rustc", "--version", "--verbose"], - stderr=subprocess.DEVNULL) + version = subprocess.check_output( + ["rustc", "--version", "--verbose"], stderr=subprocess.DEVNULL + ) version = version.decode(default_encoding) - host = next(x for x in version.split('\n') if x.startswith("host: ")) + host = next(x for x in version.split("\n") if x.startswith("host: ")) triple = host.split("host: ")[1] if verbose: - eprint("detected default triple {} from pre-installed rustc".format(triple)) + eprint( + "detected default triple {} from pre-installed rustc".format(triple) + ) return triple except Exception as e: if verbose: @@ -270,148 +307,149 @@ def default_build_triple(verbose): # If we do not have `uname`, assume Windows. if uname is None: - return 'x86_64-pc-windows-msvc' + return "x86_64-pc-windows-msvc" kernel, cputype, processor = uname.decode(default_encoding).split(maxsplit=2) # The goal here is to come up with the same triple as LLVM would, # at least for the subset of platforms we're willing to target. kerneltype_mapper = { - 'Darwin': 'apple-darwin', - 'DragonFly': 'unknown-dragonfly', - 'FreeBSD': 'unknown-freebsd', - 'Haiku': 'unknown-haiku', - 'NetBSD': 'unknown-netbsd', - 'OpenBSD': 'unknown-openbsd', - 'GNU': 'unknown-hurd', + "Darwin": "apple-darwin", + "DragonFly": "unknown-dragonfly", + "FreeBSD": "unknown-freebsd", + "Haiku": "unknown-haiku", + "NetBSD": "unknown-netbsd", + "OpenBSD": "unknown-openbsd", + "GNU": "unknown-hurd", } # Consider the direct transformation first and then the special cases if kernel in kerneltype_mapper: kernel = kerneltype_mapper[kernel] - elif kernel == 'Linux': + elif kernel == "Linux": # Apple doesn't support `-o` so this can't be used in the combined # uname invocation above ostype = require(["uname", "-o"], exit=required).decode(default_encoding) - if ostype == 'Android': - kernel = 'linux-android' + if ostype == "Android": + kernel = "linux-android" else: - kernel = 'unknown-linux-gnu' - elif kernel == 'SunOS': - kernel = 'pc-solaris' + kernel = "unknown-linux-gnu" + elif kernel == "SunOS": + kernel = "pc-solaris" # On Solaris, uname -m will return a machine classification instead # of a cpu type, so uname -p is recommended instead. However, the # output from that option is too generic for our purposes (it will # always emit 'i386' on x86/amd64 systems). As such, isainfo -k # must be used instead. - cputype = require(['isainfo', '-k']).decode(default_encoding) + cputype = require(["isainfo", "-k"]).decode(default_encoding) # sparc cpus have sun as a target vendor - if 'sparc' in cputype: - kernel = 'sun-solaris' - elif kernel.startswith('MINGW'): + if "sparc" in cputype: + kernel = "sun-solaris" + elif kernel.startswith("MINGW"): # msys' `uname` does not print gcc configuration, but prints msys # configuration. so we cannot believe `uname -m`: # msys1 is always i686 and msys2 is always x86_64. # instead, msys defines $MSYSTEM which is MINGW32 on i686 and # MINGW64 on x86_64. - kernel = 'pc-windows-gnu' - cputype = 'i686' - if os.environ.get('MSYSTEM') == 'MINGW64': - cputype = 'x86_64' - elif kernel.startswith('MSYS'): - kernel = 'pc-windows-gnu' - elif kernel.startswith('CYGWIN_NT'): - cputype = 'i686' - if kernel.endswith('WOW64'): - cputype = 'x86_64' - kernel = 'pc-windows-gnu' + kernel = "pc-windows-gnu" + cputype = "i686" + if os.environ.get("MSYSTEM") == "MINGW64": + cputype = "x86_64" + elif kernel.startswith("MSYS"): + kernel = "pc-windows-gnu" + elif kernel.startswith("CYGWIN_NT"): + cputype = "i686" + if kernel.endswith("WOW64"): + cputype = "x86_64" + kernel = "pc-windows-gnu" elif platform_is_win32(): # Some Windows platforms might have a `uname` command that returns a # non-standard string (e.g. gnuwin32 tools returns `windows32`). In # these cases, fall back to using sys.platform. - return 'x86_64-pc-windows-msvc' - elif kernel == 'AIX': + return "x86_64-pc-windows-msvc" + elif kernel == "AIX": # `uname -m` returns the machine ID rather than machine hardware on AIX, # so we are unable to use cputype to form triple. AIX 7.2 and # above supports 32-bit and 64-bit mode simultaneously and `uname -p` # returns `powerpc`, however we only supports `powerpc64-ibm-aix` in # rust on AIX. For above reasons, kerneltype_mapper and cputype_mapper # are not used to infer AIX's triple. - return 'powerpc64-ibm-aix' + return "powerpc64-ibm-aix" else: err = "unknown OS type: {}".format(kernel) sys.exit(err) - if cputype in ['powerpc', 'riscv'] and kernel == 'unknown-freebsd': - cputype = subprocess.check_output( - ['uname', '-p']).strip().decode(default_encoding) + if cputype in ["powerpc", "riscv"] and kernel == "unknown-freebsd": + cputype = ( + subprocess.check_output(["uname", "-p"]).strip().decode(default_encoding) + ) cputype_mapper = { - 'BePC': 'i686', - 'aarch64': 'aarch64', - 'aarch64eb': 'aarch64', - 'amd64': 'x86_64', - 'arm64': 'aarch64', - 'i386': 'i686', - 'i486': 'i686', - 'i686': 'i686', - 'i686-AT386': 'i686', - 'i786': 'i686', - 'loongarch64': 'loongarch64', - 'm68k': 'm68k', - 'csky': 'csky', - 'powerpc': 'powerpc', - 'powerpc64': 'powerpc64', - 'powerpc64le': 'powerpc64le', - 'ppc': 'powerpc', - 'ppc64': 'powerpc64', - 'ppc64le': 'powerpc64le', - 'riscv64': 'riscv64gc', - 's390x': 's390x', - 'x64': 'x86_64', - 'x86': 'i686', - 'x86-64': 'x86_64', - 'x86_64': 'x86_64' + "BePC": "i686", + "aarch64": "aarch64", + "aarch64eb": "aarch64", + "amd64": "x86_64", + "arm64": "aarch64", + "i386": "i686", + "i486": "i686", + "i686": "i686", + "i686-AT386": "i686", + "i786": "i686", + "loongarch64": "loongarch64", + "m68k": "m68k", + "csky": "csky", + "powerpc": "powerpc", + "powerpc64": "powerpc64", + "powerpc64le": "powerpc64le", + "ppc": "powerpc", + "ppc64": "powerpc64", + "ppc64le": "powerpc64le", + "riscv64": "riscv64gc", + "s390x": "s390x", + "x64": "x86_64", + "x86": "i686", + "x86-64": "x86_64", + "x86_64": "x86_64", } # Consider the direct transformation first and then the special cases if cputype in cputype_mapper: cputype = cputype_mapper[cputype] - elif cputype in {'xscale', 'arm'}: - cputype = 'arm' - if kernel == 'linux-android': - kernel = 'linux-androideabi' - elif kernel == 'unknown-freebsd': + elif cputype in {"xscale", "arm"}: + cputype = "arm" + if kernel == "linux-android": + kernel = "linux-androideabi" + elif kernel == "unknown-freebsd": cputype = processor - kernel = 'unknown-freebsd' - elif cputype == 'armv6l': - cputype = 'arm' - if kernel == 'linux-android': - kernel = 'linux-androideabi' + kernel = "unknown-freebsd" + elif cputype == "armv6l": + cputype = "arm" + if kernel == "linux-android": + kernel = "linux-androideabi" else: - kernel += 'eabihf' - elif cputype in {'armv7l', 'armv8l'}: - cputype = 'armv7' - if kernel == 'linux-android': - kernel = 'linux-androideabi' + kernel += "eabihf" + elif cputype in {"armv7l", "armv8l"}: + cputype = "armv7" + if kernel == "linux-android": + kernel = "linux-androideabi" else: - kernel += 'eabihf' - elif cputype == 'mips': - if sys.byteorder == 'big': - cputype = 'mips' - elif sys.byteorder == 'little': - cputype = 'mipsel' + kernel += "eabihf" + elif cputype == "mips": + if sys.byteorder == "big": + cputype = "mips" + elif sys.byteorder == "little": + cputype = "mipsel" else: raise ValueError("unknown byteorder: {}".format(sys.byteorder)) - elif cputype == 'mips64': - if sys.byteorder == 'big': - cputype = 'mips64' - elif sys.byteorder == 'little': - cputype = 'mips64el' + elif cputype == "mips64": + if sys.byteorder == "big": + cputype = "mips64" + elif sys.byteorder == "little": + cputype = "mips64el" else: - raise ValueError('unknown byteorder: {}'.format(sys.byteorder)) + raise ValueError("unknown byteorder: {}".format(sys.byteorder)) # only the n64 ABI is supported, indicate it - kernel += 'abi64' - elif cputype == 'sparc' or cputype == 'sparcv9' or cputype == 'sparc64': + kernel += "abi64" + elif cputype == "sparc" or cputype == "sparcv9" or cputype == "sparc64": pass else: err = "unknown cpu type: {}".format(cputype) @@ -422,8 +460,8 @@ def default_build_triple(verbose): @contextlib.contextmanager def output(filepath): - tmp = filepath + '.tmp' - with open(tmp, 'w') as f: + tmp = filepath + ".tmp" + with open(tmp, "w") as f: yield f try: if os.path.exists(filepath): @@ -467,6 +505,7 @@ class DownloadInfo: self.pattern = pattern self.verbose = verbose + def download_component(download_info): if not os.path.exists(download_info.tarball_path): get( @@ -477,6 +516,7 @@ def download_component(download_info): verbose=download_info.verbose, ) + def unpack_component(download_info): unpack( download_info.tarball_path, @@ -486,26 +526,30 @@ def unpack_component(download_info): verbose=download_info.verbose, ) + class FakeArgs: """Used for unit tests to avoid updating all call sites""" + def __init__(self): - self.build = '' - self.build_dir = '' + self.build = "" + self.build_dir = "" self.clean = False self.verbose = False self.json_output = False - self.color = 'auto' - self.warnings = 'default' + self.color = "auto" + self.warnings = "default" + class RustBuild(object): """Provide all the methods required to build Rust""" + def __init__(self, config_toml="", args=None): if args is None: args = FakeArgs() self.git_version = None self.nix_deps_dir = None self._should_fix_bins_and_dylibs = None - self.rust_root = os.path.abspath(os.path.join(__file__, '../../..')) + self.rust_root = os.path.abspath(os.path.join(__file__, "../../..")) self.config_toml = config_toml @@ -515,26 +559,28 @@ class RustBuild(object): self.color = args.color self.warnings = args.warnings - config_verbose_count = self.get_toml('verbose', 'build') + config_verbose_count = self.get_toml("verbose", "build") if config_verbose_count is not None: self.verbose = max(self.verbose, int(config_verbose_count)) - self.use_vendored_sources = self.get_toml('vendor', 'build') == 'true' - self.use_locked_deps = self.get_toml('locked-deps', 'build') == 'true' + self.use_vendored_sources = self.get_toml("vendor", "build") == "true" + self.use_locked_deps = self.get_toml("locked-deps", "build") == "true" - build_dir = args.build_dir or self.get_toml('build-dir', 'build') or 'build' + build_dir = args.build_dir or self.get_toml("build-dir", "build") or "build" self.build_dir = os.path.abspath(build_dir) - self.stage0_data = parse_stage0_file(os.path.join(self.rust_root, "src", "stage0")) + self.stage0_data = parse_stage0_file( + os.path.join(self.rust_root, "src", "stage0") + ) self.stage0_compiler = Stage0Toolchain( - self.stage0_data["compiler_date"], - self.stage0_data["compiler_version"] + self.stage0_data["compiler_date"], self.stage0_data["compiler_version"] + ) + self.download_url = ( + os.getenv("RUSTUP_DIST_SERVER") or self.stage0_data["dist_server"] ) - self.download_url = os.getenv("RUSTUP_DIST_SERVER") or self.stage0_data["dist_server"] self.build = args.build or self.build_triple() - def download_toolchain(self): """Fetch the build system for Rust, written in Rust @@ -550,58 +596,73 @@ class RustBuild(object): key = self.stage0_compiler.date is_outdated = self.program_out_of_date(self.rustc_stamp(), key) - need_rustc = self.rustc().startswith(bin_root) and (not os.path.exists(self.rustc()) \ - or is_outdated) - need_cargo = self.cargo().startswith(bin_root) and (not os.path.exists(self.cargo()) \ - or is_outdated) + need_rustc = self.rustc().startswith(bin_root) and ( + not os.path.exists(self.rustc()) or is_outdated + ) + need_cargo = self.cargo().startswith(bin_root) and ( + not os.path.exists(self.cargo()) or is_outdated + ) if need_rustc or need_cargo: if os.path.exists(bin_root): # HACK: On Windows, we can't delete rust-analyzer-proc-macro-server while it's # running. Kill it. if platform_is_win32(): - print("Killing rust-analyzer-proc-macro-srv before deleting stage0 toolchain") - regex = '{}\\\\(host|{})\\\\stage0\\\\libexec'.format( - os.path.basename(self.build_dir), - self.build + print( + "Killing rust-analyzer-proc-macro-srv before deleting stage0 toolchain" + ) + regex = "{}\\\\(host|{})\\\\stage0\\\\libexec".format( + os.path.basename(self.build_dir), self.build ) script = ( # NOTE: can't use `taskkill` or `Get-Process -Name` because they error if # the server isn't running. - 'Get-Process | ' + - 'Where-Object {$_.Name -eq "rust-analyzer-proc-macro-srv"} |' + - 'Where-Object {{$_.Path -match "{}"}} |'.format(regex) + - 'Stop-Process' + "Get-Process | " + + 'Where-Object {$_.Name -eq "rust-analyzer-proc-macro-srv"} |' + + 'Where-Object {{$_.Path -match "{}"}} |'.format(regex) + + "Stop-Process" ) run_powershell([script]) shutil.rmtree(bin_root) - cache_dst = (self.get_toml('bootstrap-cache-path', 'build') or - os.path.join(self.build_dir, "cache")) + cache_dst = self.get_toml("bootstrap-cache-path", "build") or os.path.join( + self.build_dir, "cache" + ) rustc_cache = os.path.join(cache_dst, key) if not os.path.exists(rustc_cache): os.makedirs(rustc_cache) - tarball_suffix = '.tar.gz' if lzma is None else '.tar.xz' + tarball_suffix = ".tar.gz" if lzma is None else ".tar.xz" - toolchain_suffix = "{}-{}{}".format(rustc_channel, self.build, tarball_suffix) + toolchain_suffix = "{}-{}{}".format( + rustc_channel, self.build, tarball_suffix + ) tarballs_to_download = [] if need_rustc: tarballs_to_download.append( - ("rust-std-{}".format(toolchain_suffix), "rust-std-{}".format(self.build)) + ( + "rust-std-{}".format(toolchain_suffix), + "rust-std-{}".format(self.build), + ) + ) + tarballs_to_download.append( + ("rustc-{}".format(toolchain_suffix), "rustc") ) - tarballs_to_download.append(("rustc-{}".format(toolchain_suffix), "rustc")) if need_cargo: - tarballs_to_download.append(("cargo-{}".format(toolchain_suffix), "cargo")) + tarballs_to_download.append( + ("cargo-{}".format(toolchain_suffix), "cargo") + ) tarballs_download_info = [ DownloadInfo( base_download_url=self.download_url, - download_path="dist/{}/{}".format(self.stage0_compiler.date, filename), + download_path="dist/{}/{}".format( + self.stage0_compiler.date, filename + ), bin_root=self.bin_root(), tarball_path=os.path.join(rustc_cache, filename), tarball_suffix=tarball_suffix, @@ -620,7 +681,11 @@ class RustBuild(object): # In Python 2.7, Pool cannot be used as a context manager. pool_size = min(len(tarballs_download_info), get_cpus()) if self.verbose: - print('Choosing a pool size of', pool_size, 'for the unpacking of the tarballs') + print( + "Choosing a pool size of", + pool_size, + "for the unpacking of the tarballs", + ) p = Pool(pool_size) try: # FIXME: A cheap workaround for https://github.com/rust-lang/rust/issues/125578, @@ -639,7 +704,9 @@ class RustBuild(object): self.fix_bin_or_dylib("{}/bin/rustc".format(bin_root)) self.fix_bin_or_dylib("{}/bin/rustdoc".format(bin_root)) - self.fix_bin_or_dylib("{}/libexec/rust-analyzer-proc-macro-srv".format(bin_root)) + self.fix_bin_or_dylib( + "{}/libexec/rust-analyzer-proc-macro-srv".format(bin_root) + ) lib_dir = "{}/lib".format(bin_root) rustlib_bin_dir = "{}/rustlib/{}/bin".format(lib_dir, self.build) self.fix_bin_or_dylib("{}/rust-lld".format(rustlib_bin_dir)) @@ -667,12 +734,15 @@ class RustBuild(object): def get_answer(): default_encoding = sys.getdefaultencoding() try: - ostype = subprocess.check_output( - ['uname', '-s']).strip().decode(default_encoding) + ostype = ( + subprocess.check_output(["uname", "-s"]) + .strip() + .decode(default_encoding) + ) except subprocess.CalledProcessError: return False except OSError as reason: - if getattr(reason, 'winerror', None) is not None: + if getattr(reason, "winerror", None) is not None: return False raise reason @@ -690,17 +760,23 @@ class RustBuild(object): # The latter one does not exist on NixOS when using tmpfs as root. try: with open("/etc/os-release", "r") as f: - is_nixos = any(ln.strip() in ("ID=nixos", "ID='nixos'", 'ID="nixos"') - for ln in f) + is_nixos = any( + ln.strip() in ("ID=nixos", "ID='nixos'", 'ID="nixos"') + for ln in f + ) except FileNotFoundError: is_nixos = False # If not on NixOS, then warn if user seems to be atop Nix shell if not is_nixos: - in_nix_shell = os.getenv('IN_NIX_SHELL') + in_nix_shell = os.getenv("IN_NIX_SHELL") if in_nix_shell: - eprint("The IN_NIX_SHELL environment variable is `{}`;".format(in_nix_shell), - "you may need to set `patch-binaries-for-nix=true` in config.toml") + eprint( + "The IN_NIX_SHELL environment variable is `{}`;".format( + in_nix_shell + ), + "you may need to set `patch-binaries-for-nix=true` in config.toml", + ) return is_nixos @@ -736,7 +812,7 @@ class RustBuild(object): # zlib: Needed as a system dependency of `libLLVM-*.so`. # patchelf: Needed for patching ELF binaries (see doc comment above). nix_deps_dir = "{}/{}".format(self.build_dir, ".nix-deps") - nix_expr = ''' + nix_expr = """ with (import {}); symlinkJoin { name = "rust-stage0-dependencies"; @@ -746,24 +822,30 @@ class RustBuild(object): stdenv.cc.bintools ]; } - ''' + """ try: - subprocess.check_output([ - "nix-build", "-E", nix_expr, "-o", nix_deps_dir, - ]) + subprocess.check_output( + [ + "nix-build", + "-E", + nix_expr, + "-o", + nix_deps_dir, + ] + ) except subprocess.CalledProcessError as reason: eprint("WARNING: failed to call nix-build:", reason) return self.nix_deps_dir = nix_deps_dir patchelf = "{}/bin/patchelf".format(nix_deps_dir) - rpath_entries = [ - os.path.join(os.path.realpath(nix_deps_dir), "lib") - ] + rpath_entries = [os.path.join(os.path.realpath(nix_deps_dir), "lib")] patchelf_args = ["--add-rpath", ":".join(rpath_entries)] if ".so" not in fname: # Finally, set the correct .interp for binaries - with open("{}/nix-support/dynamic-linker".format(nix_deps_dir)) as dynamic_linker: + with open( + "{}/nix-support/dynamic-linker".format(nix_deps_dir) + ) as dynamic_linker: patchelf_args += ["--set-interpreter", dynamic_linker.read().rstrip()] try: @@ -781,13 +863,13 @@ class RustBuild(object): >>> expected = os.path.join("build", "host", "stage0", ".rustc-stamp") >>> assert rb.rustc_stamp() == expected, rb.rustc_stamp() """ - return os.path.join(self.bin_root(), '.rustc-stamp') + return os.path.join(self.bin_root(), ".rustc-stamp") def program_out_of_date(self, stamp_path, key): """Check if the given program stamp is out of date""" if not os.path.exists(stamp_path) or self.clean: return True - with open(stamp_path, 'r') as stamp: + with open(stamp_path, "r") as stamp: return key != stamp.read() def bin_root(self): @@ -834,11 +916,11 @@ class RustBuild(object): def get_toml_static(config_toml, key, section=None): cur_section = None for line in config_toml.splitlines(): - section_match = re.match(r'^\s*\[(.*)\]\s*$', line) + section_match = re.match(r"^\s*\[(.*)\]\s*$", line) if section_match is not None: cur_section = section_match.group(1) - match = re.match(r'^{}\s*=(.*)$'.format(key), line) + match = re.match(r"^{}\s*=(.*)$".format(key), line) if match is not None: value = match.group(1) if section is None or section == cur_section: @@ -847,11 +929,11 @@ class RustBuild(object): def cargo(self): """Return config path for cargo""" - return self.program_config('cargo') + return self.program_config("cargo") def rustc(self): """Return config path for rustc""" - return self.program_config('rustc') + return self.program_config("rustc") def program_config(self, program): """Return config path for the given program at the given stage @@ -886,12 +968,12 @@ class RustBuild(object): """ start = line.find('"') if start != -1: - end = start + 1 + line[start + 1:].find('"') - return line[start + 1:end] - start = line.find('\'') + end = start + 1 + line[start + 1 :].find('"') + return line[start + 1 : end] + start = line.find("'") if start != -1: - end = start + 1 + line[start + 1:].find('\'') - return line[start + 1:end] + end = start + 1 + line[start + 1 :].find("'") + return line[start + 1 : end] return None def bootstrap_out(self): @@ -941,24 +1023,37 @@ class RustBuild(object): del env["CARGO_BUILD_TARGET"] env["CARGO_TARGET_DIR"] = build_dir env["RUSTC"] = self.rustc() - env["LD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \ - (os.pathsep + env["LD_LIBRARY_PATH"]) \ - if "LD_LIBRARY_PATH" in env else "" - env["DYLD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \ - (os.pathsep + env["DYLD_LIBRARY_PATH"]) \ - if "DYLD_LIBRARY_PATH" in env else "" - env["LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \ - (os.pathsep + env["LIBRARY_PATH"]) \ - if "LIBRARY_PATH" in env else "" - env["LIBPATH"] = os.path.join(self.bin_root(), "lib") + \ - (os.pathsep + env["LIBPATH"]) \ - if "LIBPATH" in env else "" + env["LD_LIBRARY_PATH"] = ( + os.path.join(self.bin_root(), "lib") + (os.pathsep + env["LD_LIBRARY_PATH"]) + if "LD_LIBRARY_PATH" in env + else "" + ) + env["DYLD_LIBRARY_PATH"] = ( + os.path.join(self.bin_root(), "lib") + + (os.pathsep + env["DYLD_LIBRARY_PATH"]) + if "DYLD_LIBRARY_PATH" in env + else "" + ) + env["LIBRARY_PATH"] = ( + os.path.join(self.bin_root(), "lib") + (os.pathsep + env["LIBRARY_PATH"]) + if "LIBRARY_PATH" in env + else "" + ) + env["LIBPATH"] = ( + os.path.join(self.bin_root(), "lib") + (os.pathsep + env["LIBPATH"]) + if "LIBPATH" in env + else "" + ) # Export Stage0 snapshot compiler related env variables build_section = "target.{}".format(self.build) host_triple_sanitized = self.build.replace("-", "_") var_data = { - "CC": "cc", "CXX": "cxx", "LD": "linker", "AR": "ar", "RANLIB": "ranlib" + "CC": "cc", + "CXX": "cxx", + "LD": "linker", + "AR": "ar", + "RANLIB": "ranlib", } for var_name, toml_key in var_data.items(): toml_val = self.get_toml(toml_key, build_section) @@ -1023,14 +1118,16 @@ class RustBuild(object): if "RUSTFLAGS_BOOTSTRAP" in env: env["RUSTFLAGS"] += " " + env["RUSTFLAGS_BOOTSTRAP"] - env["PATH"] = os.path.join(self.bin_root(), "bin") + \ - os.pathsep + env["PATH"] + env["PATH"] = os.path.join(self.bin_root(), "bin") + os.pathsep + env["PATH"] if not os.path.isfile(self.cargo()): - raise Exception("no cargo executable found at `{}`".format( - self.cargo())) - args = [self.cargo(), "build", "--manifest-path", - os.path.join(self.rust_root, "src/bootstrap/Cargo.toml"), - "-Zroot-dir="+self.rust_root] + raise Exception("no cargo executable found at `{}`".format(self.cargo())) + args = [ + self.cargo(), + "build", + "--manifest-path", + os.path.join(self.rust_root, "src/bootstrap/Cargo.toml"), + "-Zroot-dir=" + self.rust_root, + ] args.extend("--verbose" for _ in range(self.verbose)) if self.use_locked_deps: args.append("--locked") @@ -1058,83 +1155,103 @@ class RustBuild(object): Note that `default_build_triple` is moderately expensive, so use `self.build` where possible. """ - config = self.get_toml('build') + config = self.get_toml("build") return config or default_build_triple(self.verbose) def check_vendored_status(self): """Check that vendoring is configured properly""" # keep this consistent with the equivalent check in bootstrap: # https://github.com/rust-lang/rust/blob/a8a33cf27166d3eabaffc58ed3799e054af3b0c6/src/bootstrap/lib.rs#L399-L405 - if 'SUDO_USER' in os.environ and not self.use_vendored_sources: + if "SUDO_USER" in os.environ and not self.use_vendored_sources: if os.getuid() == 0: self.use_vendored_sources = True - eprint('INFO: looks like you\'re trying to run this command as root') - eprint(' and so in order to preserve your $HOME this will now') - eprint(' use vendored sources by default.') + eprint("INFO: looks like you're trying to run this command as root") + eprint(" and so in order to preserve your $HOME this will now") + eprint(" use vendored sources by default.") - cargo_dir = os.path.join(self.rust_root, '.cargo') + cargo_dir = os.path.join(self.rust_root, ".cargo") + url = "https://ci-artifacts.rust-lang.org/rustc-builds//rustc-nightly-src.tar.xz" if self.use_vendored_sources: - vendor_dir = os.path.join(self.rust_root, 'vendor') + vendor_dir = os.path.join(self.rust_root, "vendor") if not os.path.exists(vendor_dir): - eprint('ERROR: vendoring required, but vendor directory does not exist.') - eprint(' Run `x.py vendor` to initialize the vendor directory.') - eprint(' Alternatively, use the pre-vendored `rustc-src` dist component.') - eprint(' To get a stable/beta/nightly version, download it from: ') - eprint(' ' - 'https://forge.rust-lang.org/infra/other-installation-methods.html#source-code') - eprint(' To get a specific commit version, download it using the below URL,') - eprint(' replacing with a specific commit checksum: ') - eprint(' ' - 'https://ci-artifacts.rust-lang.org/rustc-builds//rustc-nightly-src.tar.xz') - eprint(' Once you have the source downloaded, place the vendor directory') - eprint(' from the archive in the root of the rust project.') + eprint( + "ERROR: vendoring required, but vendor directory does not exist." + ) + eprint(" Run `x.py vendor` to initialize the vendor directory.") + eprint( + " Alternatively, use the pre-vendored `rustc-src` dist component." + ) + eprint( + " To get a stable/beta/nightly version, download it from: " + ) + eprint( + " " + "https://forge.rust-lang.org/infra/other-installation-methods.html#source-code" + ) + eprint( + " To get a specific commit version, download it using the below URL," + ) + eprint(" replacing with a specific commit checksum: ") + eprint(" ", url) + eprint( + " Once you have the source downloaded, place the vendor directory" + ) + eprint(" from the archive in the root of the rust project.") raise Exception("{} not found".format(vendor_dir)) if not os.path.exists(cargo_dir): - eprint('ERROR: vendoring required, but .cargo/config does not exist.') + eprint("ERROR: vendoring required, but .cargo/config does not exist.") raise Exception("{} not found".format(cargo_dir)) + def parse_args(args): """Parse the command line arguments that the python script needs.""" parser = argparse.ArgumentParser(add_help=False) - parser.add_argument('-h', '--help', action='store_true') - parser.add_argument('--config') - parser.add_argument('--build-dir') - parser.add_argument('--build') - parser.add_argument('--color', choices=['always', 'never', 'auto']) - parser.add_argument('--clean', action='store_true') - parser.add_argument('--json-output', action='store_true') - parser.add_argument('--warnings', choices=['deny', 'warn', 'default'], default='default') - parser.add_argument('-v', '--verbose', action='count', default=0) + parser.add_argument("-h", "--help", action="store_true") + parser.add_argument("--config") + parser.add_argument("--build-dir") + parser.add_argument("--build") + parser.add_argument("--color", choices=["always", "never", "auto"]) + parser.add_argument("--clean", action="store_true") + parser.add_argument("--json-output", action="store_true") + parser.add_argument( + "--warnings", choices=["deny", "warn", "default"], default="default" + ) + parser.add_argument("-v", "--verbose", action="count", default=0) return parser.parse_known_args(args)[0] + def parse_stage0_file(path): result = {} - with open(path, 'r') as file: + with open(path, "r") as file: for line in file: line = line.strip() - if line and not line.startswith('#'): - key, value = line.split('=', 1) + if line and not line.startswith("#"): + key, value = line.split("=", 1) result[key.strip()] = value.strip() return result + def bootstrap(args): """Configure, fetch, build and run the initial bootstrap""" - rust_root = os.path.abspath(os.path.join(__file__, '../../..')) + rust_root = os.path.abspath(os.path.join(__file__, "../../..")) - if not os.path.exists(os.path.join(rust_root, '.git')) and \ - os.path.exists(os.path.join(rust_root, '.github')): - eprint("warn: Looks like you are trying to bootstrap Rust from a source that is neither a " - "git clone nor distributed tarball.\nThis build may fail due to missing submodules " - "unless you put them in place manually.") + if not os.path.exists(os.path.join(rust_root, ".git")) and os.path.exists( + os.path.join(rust_root, ".github") + ): + eprint( + "warn: Looks like you are trying to bootstrap Rust from a source that is neither a " + "git clone nor distributed tarball.\nThis build may fail due to missing submodules " + "unless you put them in place manually." + ) # Read from `--config`, then `RUST_BOOTSTRAP_CONFIG`, then `./config.toml`, # then `config.toml` in the root directory. - toml_path = args.config or os.getenv('RUST_BOOTSTRAP_CONFIG') + toml_path = args.config or os.getenv("RUST_BOOTSTRAP_CONFIG") using_default_path = toml_path is None if using_default_path: - toml_path = 'config.toml' + toml_path = "config.toml" if not os.path.exists(toml_path): toml_path = os.path.join(rust_root, toml_path) @@ -1144,23 +1261,23 @@ def bootstrap(args): with open(toml_path) as config: config_toml = config.read() else: - config_toml = '' + config_toml = "" - profile = RustBuild.get_toml_static(config_toml, 'profile') + profile = RustBuild.get_toml_static(config_toml, "profile") if profile is not None: # Allows creating alias for profile names, allowing # profiles to be renamed while maintaining back compatibility # Keep in sync with `profile_aliases` in config.rs - profile_aliases = { - "user": "dist" - } - include_file = 'config.{}.toml'.format(profile_aliases.get(profile) or profile) - include_dir = os.path.join(rust_root, 'src', 'bootstrap', 'defaults') + profile_aliases = {"user": "dist"} + include_file = "config.{}.toml".format(profile_aliases.get(profile) or profile) + include_dir = os.path.join(rust_root, "src", "bootstrap", "defaults") include_path = os.path.join(include_dir, include_file) if not os.path.exists(include_path): - raise Exception("Unrecognized config profile '{}'. Check src/bootstrap/defaults" - " for available options.".format(profile)) + raise Exception( + "Unrecognized config profile '{}'. Check src/bootstrap/defaults" + " for available options.".format(profile) + ) # HACK: This works because `self.get_toml()` returns the first match it finds for a # specific key, so appending our defaults at the end allows the user to override them @@ -1194,8 +1311,8 @@ def main(): start_time = time() # x.py help ... - if len(sys.argv) > 1 and sys.argv[1] == 'help': - sys.argv[1] = '-h' + if len(sys.argv) > 1 and sys.argv[1] == "help": + sys.argv[1] = "-h" args = parse_args(sys.argv) help_triggered = args.help or len(sys.argv) == 1 @@ -1205,14 +1322,15 @@ def main(): if help_triggered: eprint( "INFO: Downloading and building bootstrap before processing --help command.\n" - " See src/bootstrap/README.md for help with common commands.") + " See src/bootstrap/README.md for help with common commands." + ) exit_code = 0 success_word = "successfully" try: bootstrap(args) except (SystemExit, KeyboardInterrupt) as error: - if hasattr(error, 'code') and isinstance(error.code, int): + if hasattr(error, "code") and isinstance(error.code, int): exit_code = error.code else: exit_code = 1 @@ -1220,9 +1338,14 @@ def main(): success_word = "unsuccessfully" if not help_triggered: - eprint("Build completed", success_word, "in", format_build_time(time() - start_time)) + eprint( + "Build completed", + success_word, + "in", + format_build_time(time() - start_time), + ) sys.exit(exit_code) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py index 70ed12b96e8..7494536539d 100644 --- a/src/bootstrap/bootstrap_test.py +++ b/src/bootstrap/bootstrap_test.py @@ -16,8 +16,9 @@ from shutil import rmtree bootstrap_dir = os.path.dirname(os.path.abspath(__file__)) # For the import below, have Python search in src/bootstrap first. sys.path.insert(0, bootstrap_dir) -import bootstrap # noqa: E402 -import configure # noqa: E402 +import bootstrap # noqa: E402 +import configure # noqa: E402 + def serialize_and_parse(configure_args, bootstrap_args=None): from io import StringIO @@ -32,15 +33,20 @@ def serialize_and_parse(configure_args, bootstrap_args=None): try: import tomllib + # Verify this is actually valid TOML. tomllib.loads(build.config_toml) except ImportError: - print("WARNING: skipping TOML validation, need at least python 3.11", file=sys.stderr) + print( + "WARNING: skipping TOML validation, need at least python 3.11", + file=sys.stderr, + ) return build class VerifyTestCase(unittest.TestCase): """Test Case for verify""" + def setUp(self): self.container = tempfile.mkdtemp() self.src = os.path.join(self.container, "src.txt") @@ -68,14 +74,14 @@ class VerifyTestCase(unittest.TestCase): class ProgramOutOfDate(unittest.TestCase): """Test if a program is out of date""" + def setUp(self): self.container = tempfile.mkdtemp() os.mkdir(os.path.join(self.container, "stage0")) self.build = bootstrap.RustBuild() self.build.date = "2017-06-15" self.build.build_dir = self.container - self.rustc_stamp_path = os.path.join(self.container, "stage0", - ".rustc-stamp") + self.rustc_stamp_path = os.path.join(self.container, "stage0", ".rustc-stamp") self.key = self.build.date + str(None) def tearDown(self): @@ -97,11 +103,14 @@ class ProgramOutOfDate(unittest.TestCase): """Return False both dates match""" with open(self.rustc_stamp_path, "w") as rustc_stamp: rustc_stamp.write("2017-06-15None") - self.assertFalse(self.build.program_out_of_date(self.rustc_stamp_path, self.key)) + self.assertFalse( + self.build.program_out_of_date(self.rustc_stamp_path, self.key) + ) class ParseArgsInConfigure(unittest.TestCase): """Test if `parse_args` function in `configure.py` works properly""" + @patch("configure.err") def test_unknown_args(self, err): # It should be print an error message if the argument doesn't start with '--' @@ -148,28 +157,35 @@ class ParseArgsInConfigure(unittest.TestCase): class GenerateAndParseConfig(unittest.TestCase): """Test that we can serialize and deserialize a config.toml file""" + def test_no_args(self): build = serialize_and_parse([]) - self.assertEqual(build.get_toml("profile"), 'dist') + self.assertEqual(build.get_toml("profile"), "dist") self.assertIsNone(build.get_toml("llvm.download-ci-llvm")) def test_set_section(self): build = serialize_and_parse(["--set", "llvm.download-ci-llvm"]) - self.assertEqual(build.get_toml("download-ci-llvm", section="llvm"), 'true') + self.assertEqual(build.get_toml("download-ci-llvm", section="llvm"), "true") def test_set_target(self): build = serialize_and_parse(["--set", "target.x86_64-unknown-linux-gnu.cc=gcc"]) - self.assertEqual(build.get_toml("cc", section="target.x86_64-unknown-linux-gnu"), 'gcc') + self.assertEqual( + build.get_toml("cc", section="target.x86_64-unknown-linux-gnu"), "gcc" + ) def test_set_top_level(self): build = serialize_and_parse(["--set", "profile=compiler"]) - self.assertEqual(build.get_toml("profile"), 'compiler') + self.assertEqual(build.get_toml("profile"), "compiler") def test_set_codegen_backends(self): build = serialize_and_parse(["--set", "rust.codegen-backends=cranelift"]) - self.assertNotEqual(build.config_toml.find("codegen-backends = ['cranelift']"), -1) + self.assertNotEqual( + build.config_toml.find("codegen-backends = ['cranelift']"), -1 + ) build = serialize_and_parse(["--set", "rust.codegen-backends=cranelift,llvm"]) - self.assertNotEqual(build.config_toml.find("codegen-backends = ['cranelift', 'llvm']"), -1) + self.assertNotEqual( + build.config_toml.find("codegen-backends = ['cranelift', 'llvm']"), -1 + ) build = serialize_and_parse(["--enable-full-tools"]) self.assertNotEqual(build.config_toml.find("codegen-backends = ['llvm']"), -1) @@ -223,7 +239,7 @@ class BuildBootstrap(unittest.TestCase): self.assertTrue("--timings" in args) def test_warnings(self): - for toml_warnings in ['false', 'true', None]: + for toml_warnings in ["false", "true", None]: configure_args = [] if toml_warnings is not None: configure_args = ["--set", "rust.deny-warnings=" + toml_warnings] diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 70f4e70962a..71750022145 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -6,11 +6,12 @@ from __future__ import absolute_import, division, print_function import shlex import sys import os + rust_dir = os.path.dirname(os.path.abspath(__file__)) rust_dir = os.path.dirname(rust_dir) rust_dir = os.path.dirname(rust_dir) sys.path.append(os.path.join(rust_dir, "src", "bootstrap")) -import bootstrap # noqa: E402 +import bootstrap # noqa: E402 class Option(object): @@ -32,26 +33,62 @@ def v(*args): options.append(Option(*args, value=True)) -o("debug", "rust.debug", "enables debugging environment; does not affect optimization of bootstrapped code") +o( + "debug", + "rust.debug", + "enables debugging environment; does not affect optimization of bootstrapped code", +) o("docs", "build.docs", "build standard library documentation") o("compiler-docs", "build.compiler-docs", "build compiler documentation") o("optimize-tests", "rust.optimize-tests", "build tests with optimizations") o("verbose-tests", "rust.verbose-tests", "enable verbose output when running tests") -o("ccache", "llvm.ccache", "invoke gcc/clang via ccache to reuse object files between builds") +o( + "ccache", + "llvm.ccache", + "invoke gcc/clang via ccache to reuse object files between builds", +) o("sccache", None, "invoke gcc/clang via sccache to reuse object files between builds") o("local-rust", None, "use an installed rustc rather than downloading a snapshot") v("local-rust-root", None, "set prefix for local rust binary") -o("local-rebuild", "build.local-rebuild", "assume local-rust matches the current version, for rebuilds; implies local-rust, and is implied if local-rust already matches the current version") -o("llvm-static-stdcpp", "llvm.static-libstdcpp", "statically link to libstdc++ for LLVM") -o("llvm-link-shared", "llvm.link-shared", "prefer shared linking to LLVM (llvm-config --link-shared)") +o( + "local-rebuild", + "build.local-rebuild", + "assume local-rust matches the current version, for rebuilds; implies local-rust, and is implied if local-rust already matches the current version", +) +o( + "llvm-static-stdcpp", + "llvm.static-libstdcpp", + "statically link to libstdc++ for LLVM", +) +o( + "llvm-link-shared", + "llvm.link-shared", + "prefer shared linking to LLVM (llvm-config --link-shared)", +) o("rpath", "rust.rpath", "build rpaths into rustc itself") o("codegen-tests", "rust.codegen-tests", "run the tests/codegen tests") -o("ninja", "llvm.ninja", "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)") +o( + "ninja", + "llvm.ninja", + "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)", +) o("locked-deps", "build.locked-deps", "force Cargo.lock to be up to date") o("vendor", "build.vendor", "enable usage of vendored Rust crates") -o("sanitizers", "build.sanitizers", "build the sanitizer runtimes (asan, dfsan, lsan, msan, tsan, hwasan)") -o("dist-src", "rust.dist-src", "when building tarballs enables building a source tarball") -o("cargo-native-static", "build.cargo-native-static", "static native libraries in cargo") +o( + "sanitizers", + "build.sanitizers", + "build the sanitizer runtimes (asan, dfsan, lsan, msan, tsan, hwasan)", +) +o( + "dist-src", + "rust.dist-src", + "when building tarballs enables building a source tarball", +) +o( + "cargo-native-static", + "build.cargo-native-static", + "static native libraries in cargo", +) o("profiler", "build.profiler", "build the profiler runtime") o("full-tools", None, "enable all tools") o("lld", "rust.lld", "build lld") @@ -59,7 +96,11 @@ o("llvm-bitcode-linker", "rust.llvm-bitcode-linker", "build llvm bitcode linker" o("clang", "llvm.clang", "build clang") o("use-libcxx", "llvm.use-libcxx", "build LLVM with libc++") o("control-flow-guard", "rust.control-flow-guard", "Enable Control Flow Guard") -o("patch-binaries-for-nix", "build.patch-binaries-for-nix", "whether patch binaries for usage with Nix toolchains") +o( + "patch-binaries-for-nix", + "build.patch-binaries-for-nix", + "whether patch binaries for usage with Nix toolchains", +) o("new-symbol-mangling", "rust.new-symbol-mangling", "use symbol-mangling-version v0") v("llvm-cflags", "llvm.cflags", "build LLVM with these extra compiler flags") @@ -76,16 +117,48 @@ o("llvm-enzyme", "llvm.enzyme", "build LLVM with enzyme") o("llvm-offload", "llvm.offload", "build LLVM with gpu offload support") o("llvm-plugins", "llvm.plugins", "build LLVM with plugin interface") o("debug-assertions", "rust.debug-assertions", "build with debugging assertions") -o("debug-assertions-std", "rust.debug-assertions-std", "build the standard library with debugging assertions") +o( + "debug-assertions-std", + "rust.debug-assertions-std", + "build the standard library with debugging assertions", +) o("overflow-checks", "rust.overflow-checks", "build with overflow checks") -o("overflow-checks-std", "rust.overflow-checks-std", "build the standard library with overflow checks") -o("llvm-release-debuginfo", "llvm.release-debuginfo", "build LLVM with debugger metadata") +o( + "overflow-checks-std", + "rust.overflow-checks-std", + "build the standard library with overflow checks", +) +o( + "llvm-release-debuginfo", + "llvm.release-debuginfo", + "build LLVM with debugger metadata", +) v("debuginfo-level", "rust.debuginfo-level", "debuginfo level for Rust code") -v("debuginfo-level-rustc", "rust.debuginfo-level-rustc", "debuginfo level for the compiler") -v("debuginfo-level-std", "rust.debuginfo-level-std", "debuginfo level for the standard library") -v("debuginfo-level-tools", "rust.debuginfo-level-tools", "debuginfo level for the tools") -v("debuginfo-level-tests", "rust.debuginfo-level-tests", "debuginfo level for the test suites run with compiletest") -v("save-toolstates", "rust.save-toolstates", "save build and test status of external tools into this file") +v( + "debuginfo-level-rustc", + "rust.debuginfo-level-rustc", + "debuginfo level for the compiler", +) +v( + "debuginfo-level-std", + "rust.debuginfo-level-std", + "debuginfo level for the standard library", +) +v( + "debuginfo-level-tools", + "rust.debuginfo-level-tools", + "debuginfo level for the tools", +) +v( + "debuginfo-level-tests", + "rust.debuginfo-level-tests", + "debuginfo level for the test suites run with compiletest", +) +v( + "save-toolstates", + "rust.save-toolstates", + "save build and test status of external tools into this file", +) v("prefix", "install.prefix", "set installation prefix") v("localstatedir", "install.localstatedir", "local state directory") @@ -102,50 +175,117 @@ v("llvm-config", None, "set path to llvm-config") v("llvm-filecheck", None, "set path to LLVM's FileCheck utility") v("python", "build.python", "set path to python") v("android-ndk", "build.android-ndk", "set path to Android NDK") -v("musl-root", "target.x86_64-unknown-linux-musl.musl-root", - "MUSL root installation directory (deprecated)") -v("musl-root-x86_64", "target.x86_64-unknown-linux-musl.musl-root", - "x86_64-unknown-linux-musl install directory") -v("musl-root-i586", "target.i586-unknown-linux-musl.musl-root", - "i586-unknown-linux-musl install directory") -v("musl-root-i686", "target.i686-unknown-linux-musl.musl-root", - "i686-unknown-linux-musl install directory") -v("musl-root-arm", "target.arm-unknown-linux-musleabi.musl-root", - "arm-unknown-linux-musleabi install directory") -v("musl-root-armhf", "target.arm-unknown-linux-musleabihf.musl-root", - "arm-unknown-linux-musleabihf install directory") -v("musl-root-armv5te", "target.armv5te-unknown-linux-musleabi.musl-root", - "armv5te-unknown-linux-musleabi install directory") -v("musl-root-armv7", "target.armv7-unknown-linux-musleabi.musl-root", - "armv7-unknown-linux-musleabi install directory") -v("musl-root-armv7hf", "target.armv7-unknown-linux-musleabihf.musl-root", - "armv7-unknown-linux-musleabihf install directory") -v("musl-root-aarch64", "target.aarch64-unknown-linux-musl.musl-root", - "aarch64-unknown-linux-musl install directory") -v("musl-root-mips", "target.mips-unknown-linux-musl.musl-root", - "mips-unknown-linux-musl install directory") -v("musl-root-mipsel", "target.mipsel-unknown-linux-musl.musl-root", - "mipsel-unknown-linux-musl install directory") -v("musl-root-mips64", "target.mips64-unknown-linux-muslabi64.musl-root", - "mips64-unknown-linux-muslabi64 install directory") -v("musl-root-mips64el", "target.mips64el-unknown-linux-muslabi64.musl-root", - "mips64el-unknown-linux-muslabi64 install directory") -v("musl-root-riscv32gc", "target.riscv32gc-unknown-linux-musl.musl-root", - "riscv32gc-unknown-linux-musl install directory") -v("musl-root-riscv64gc", "target.riscv64gc-unknown-linux-musl.musl-root", - "riscv64gc-unknown-linux-musl install directory") -v("musl-root-loongarch64", "target.loongarch64-unknown-linux-musl.musl-root", - "loongarch64-unknown-linux-musl install directory") -v("qemu-armhf-rootfs", "target.arm-unknown-linux-gnueabihf.qemu-rootfs", - "rootfs in qemu testing, you probably don't want to use this") -v("qemu-aarch64-rootfs", "target.aarch64-unknown-linux-gnu.qemu-rootfs", - "rootfs in qemu testing, you probably don't want to use this") -v("qemu-riscv64-rootfs", "target.riscv64gc-unknown-linux-gnu.qemu-rootfs", - "rootfs in qemu testing, you probably don't want to use this") -v("experimental-targets", "llvm.experimental-targets", - "experimental LLVM targets to build") +v( + "musl-root", + "target.x86_64-unknown-linux-musl.musl-root", + "MUSL root installation directory (deprecated)", +) +v( + "musl-root-x86_64", + "target.x86_64-unknown-linux-musl.musl-root", + "x86_64-unknown-linux-musl install directory", +) +v( + "musl-root-i586", + "target.i586-unknown-linux-musl.musl-root", + "i586-unknown-linux-musl install directory", +) +v( + "musl-root-i686", + "target.i686-unknown-linux-musl.musl-root", + "i686-unknown-linux-musl install directory", +) +v( + "musl-root-arm", + "target.arm-unknown-linux-musleabi.musl-root", + "arm-unknown-linux-musleabi install directory", +) +v( + "musl-root-armhf", + "target.arm-unknown-linux-musleabihf.musl-root", + "arm-unknown-linux-musleabihf install directory", +) +v( + "musl-root-armv5te", + "target.armv5te-unknown-linux-musleabi.musl-root", + "armv5te-unknown-linux-musleabi install directory", +) +v( + "musl-root-armv7", + "target.armv7-unknown-linux-musleabi.musl-root", + "armv7-unknown-linux-musleabi install directory", +) +v( + "musl-root-armv7hf", + "target.armv7-unknown-linux-musleabihf.musl-root", + "armv7-unknown-linux-musleabihf install directory", +) +v( + "musl-root-aarch64", + "target.aarch64-unknown-linux-musl.musl-root", + "aarch64-unknown-linux-musl install directory", +) +v( + "musl-root-mips", + "target.mips-unknown-linux-musl.musl-root", + "mips-unknown-linux-musl install directory", +) +v( + "musl-root-mipsel", + "target.mipsel-unknown-linux-musl.musl-root", + "mipsel-unknown-linux-musl install directory", +) +v( + "musl-root-mips64", + "target.mips64-unknown-linux-muslabi64.musl-root", + "mips64-unknown-linux-muslabi64 install directory", +) +v( + "musl-root-mips64el", + "target.mips64el-unknown-linux-muslabi64.musl-root", + "mips64el-unknown-linux-muslabi64 install directory", +) +v( + "musl-root-riscv32gc", + "target.riscv32gc-unknown-linux-musl.musl-root", + "riscv32gc-unknown-linux-musl install directory", +) +v( + "musl-root-riscv64gc", + "target.riscv64gc-unknown-linux-musl.musl-root", + "riscv64gc-unknown-linux-musl install directory", +) +v( + "musl-root-loongarch64", + "target.loongarch64-unknown-linux-musl.musl-root", + "loongarch64-unknown-linux-musl install directory", +) +v( + "qemu-armhf-rootfs", + "target.arm-unknown-linux-gnueabihf.qemu-rootfs", + "rootfs in qemu testing, you probably don't want to use this", +) +v( + "qemu-aarch64-rootfs", + "target.aarch64-unknown-linux-gnu.qemu-rootfs", + "rootfs in qemu testing, you probably don't want to use this", +) +v( + "qemu-riscv64-rootfs", + "target.riscv64gc-unknown-linux-gnu.qemu-rootfs", + "rootfs in qemu testing, you probably don't want to use this", +) +v( + "experimental-targets", + "llvm.experimental-targets", + "experimental LLVM targets to build", +) v("release-channel", "rust.channel", "the name of the release channel to build") -v("release-description", "rust.description", "optional descriptive string for version output") +v( + "release-description", + "rust.description", + "optional descriptive string for version output", +) v("dist-compression-formats", None, "List of compression formats to use") # Used on systems where "cc" is unavailable @@ -154,7 +294,11 @@ v("default-linker", "rust.default-linker", "the default linker") # Many of these are saved below during the "writing configuration" step # (others are conditionally saved). o("manage-submodules", "build.submodules", "let the build manage the git submodules") -o("full-bootstrap", "build.full-bootstrap", "build three compilers instead of two (not recommended except for testing reproducible builds)") +o( + "full-bootstrap", + "build.full-bootstrap", + "build three compilers instead of two (not recommended except for testing reproducible builds)", +) o("extended", "build.extended", "build an extended rust tool set") v("bootstrap-cache-path", None, "use provided path for the bootstrap cache") @@ -165,8 +309,16 @@ v("host", None, "List of GNUs ./configure syntax LLVM host triples") v("target", None, "List of GNUs ./configure syntax LLVM target triples") # Options specific to this configure script -o("option-checking", None, "complain about unrecognized options in this configure script") -o("verbose-configure", None, "don't truncate options when printing them in this configure script") +o( + "option-checking", + None, + "complain about unrecognized options in this configure script", +) +o( + "verbose-configure", + None, + "don't truncate options when printing them in this configure script", +) v("set", None, "set arbitrary key/value pairs in TOML configuration") @@ -178,39 +330,42 @@ def err(msg): print("\nconfigure: ERROR: " + msg + "\n") sys.exit(1) + def is_value_list(key): for option in options: - if option.name == key and option.desc.startswith('List of'): + if option.name == key and option.desc.startswith("List of"): return True return False -if '--help' in sys.argv or '-h' in sys.argv: - print('Usage: ./configure [options]') - print('') - print('Options') + +if "--help" in sys.argv or "-h" in sys.argv: + print("Usage: ./configure [options]") + print("") + print("Options") for option in options: - if 'android' in option.name: + if "android" in option.name: # no one needs to know about these obscure options continue if option.value: - print('\t{:30} {}'.format('--{}=VAL'.format(option.name), option.desc)) + print("\t{:30} {}".format("--{}=VAL".format(option.name), option.desc)) else: - print('\t--enable-{:25} OR --disable-{}'.format(option.name, option.name)) - print('\t\t' + option.desc) - print('') - print('This configure script is a thin configuration shim over the true') - print('configuration system, `config.toml`. You can explore the comments') - print('in `config.example.toml` next to this configure script to see') - print('more information about what each option is. Additionally you can') - print('pass `--set` as an argument to set arbitrary key/value pairs') - print('in the TOML configuration if desired') - print('') - print('Also note that all options which take `--enable` can similarly') - print('be passed with `--disable-foo` to forcibly disable the option') + print("\t--enable-{:25} OR --disable-{}".format(option.name, option.name)) + print("\t\t" + option.desc) + print("") + print("This configure script is a thin configuration shim over the true") + print("configuration system, `config.toml`. You can explore the comments") + print("in `config.example.toml` next to this configure script to see") + print("more information about what each option is. Additionally you can") + print("pass `--set` as an argument to set arbitrary key/value pairs") + print("in the TOML configuration if desired") + print("") + print("Also note that all options which take `--enable` can similarly") + print("be passed with `--disable-foo` to forcibly disable the option") sys.exit(0) VERBOSE = False + # Parse all command line arguments into one of these three lists, handling # boolean and value-based options separately def parse_args(args): @@ -222,7 +377,7 @@ def parse_args(args): while i < len(args): arg = args[i] i += 1 - if not arg.startswith('--'): + if not arg.startswith("--"): unknown_args.append(arg) continue @@ -230,7 +385,7 @@ def parse_args(args): for option in options: value = None if option.value: - keyval = arg[2:].split('=', 1) + keyval = arg[2:].split("=", 1) key = keyval[0] if option.name != key: continue @@ -244,9 +399,9 @@ def parse_args(args): need_value_args.append(arg) continue else: - if arg[2:] == 'enable-' + option.name: + if arg[2:] == "enable-" + option.name: value = True - elif arg[2:] == 'disable-' + option.name: + elif arg[2:] == "disable-" + option.name: value = False else: continue @@ -263,8 +418,9 @@ def parse_args(args): # NOTE: here and a few other places, we use [-1] to apply the *last* value # passed. But if option-checking is enabled, then the known_args loop will # also assert that options are only passed once. - option_checking = ('option-checking' not in known_args - or known_args['option-checking'][-1][1]) + option_checking = ( + "option-checking" not in known_args or known_args["option-checking"][-1][1] + ) if option_checking: if len(unknown_args) > 0: err("Option '" + unknown_args[0] + "' is not recognized") @@ -272,18 +428,18 @@ def parse_args(args): err("Option '{0}' needs a value ({0}=val)".format(need_value_args[0])) global VERBOSE - VERBOSE = 'verbose-configure' in known_args + VERBOSE = "verbose-configure" in known_args config = {} - set('build.configure-args', args, config) + set("build.configure-args", args, config) apply_args(known_args, option_checking, config) return parse_example_config(known_args, config) def build(known_args): - if 'build' in known_args: - return known_args['build'][-1][1] + if "build" in known_args: + return known_args["build"][-1][1] return bootstrap.default_build_triple(verbose=False) @@ -291,7 +447,7 @@ def set(key, value, config): if isinstance(value, list): # Remove empty values, which value.split(',') tends to generate and # replace single quotes for double quotes to ensure correct parsing. - value = [v.replace('\'', '"') for v in value if v] + value = [v.replace("'", '"') for v in value if v] s = "{:20} := {}".format(key, value) if len(s) < 70 or VERBOSE: @@ -310,7 +466,7 @@ def set(key, value, config): for i, part in enumerate(parts): if i == len(parts) - 1: if is_value_list(part) and isinstance(value, str): - value = value.split(',') + value = value.split(",") arr[part] = value else: if part not in arr: @@ -321,9 +477,9 @@ def set(key, value, config): def apply_args(known_args, option_checking, config): for key in known_args: # The `set` option is special and can be passed a bunch of times - if key == 'set': + if key == "set": for _option, value in known_args[key]: - keyval = value.split('=', 1) + keyval = value.split("=", 1) if len(keyval) == 1 or keyval[1] == "true": value = True elif keyval[1] == "false": @@ -348,50 +504,55 @@ def apply_args(known_args, option_checking, config): # that here. build_triple = build(known_args) - if option.name == 'sccache': - set('llvm.ccache', 'sccache', config) - elif option.name == 'local-rust': - for path in os.environ['PATH'].split(os.pathsep): - if os.path.exists(path + '/rustc'): - set('build.rustc', path + '/rustc', config) + if option.name == "sccache": + set("llvm.ccache", "sccache", config) + elif option.name == "local-rust": + for path in os.environ["PATH"].split(os.pathsep): + if os.path.exists(path + "/rustc"): + set("build.rustc", path + "/rustc", config) break - for path in os.environ['PATH'].split(os.pathsep): - if os.path.exists(path + '/cargo'): - set('build.cargo', path + '/cargo', config) + for path in os.environ["PATH"].split(os.pathsep): + if os.path.exists(path + "/cargo"): + set("build.cargo", path + "/cargo", config) break - elif option.name == 'local-rust-root': - set('build.rustc', value + '/bin/rustc', config) - set('build.cargo', value + '/bin/cargo', config) - elif option.name == 'llvm-root': - set('target.{}.llvm-config'.format(build_triple), value + '/bin/llvm-config', config) - elif option.name == 'llvm-config': - set('target.{}.llvm-config'.format(build_triple), value, config) - elif option.name == 'llvm-filecheck': - set('target.{}.llvm-filecheck'.format(build_triple), value, config) - elif option.name == 'tools': - set('build.tools', value.split(','), config) - elif option.name == 'bootstrap-cache-path': - set('build.bootstrap-cache-path', value, config) - elif option.name == 'codegen-backends': - set('rust.codegen-backends', value.split(','), config) - elif option.name == 'host': - set('build.host', value.split(','), config) - elif option.name == 'target': - set('build.target', value.split(','), config) - elif option.name == 'full-tools': - set('rust.codegen-backends', ['llvm'], config) - set('rust.lld', True, config) - set('rust.llvm-tools', True, config) - set('rust.llvm-bitcode-linker', True, config) - set('build.extended', True, config) - elif option.name in ['option-checking', 'verbose-configure']: + elif option.name == "local-rust-root": + set("build.rustc", value + "/bin/rustc", config) + set("build.cargo", value + "/bin/cargo", config) + elif option.name == "llvm-root": + set( + "target.{}.llvm-config".format(build_triple), + value + "/bin/llvm-config", + config, + ) + elif option.name == "llvm-config": + set("target.{}.llvm-config".format(build_triple), value, config) + elif option.name == "llvm-filecheck": + set("target.{}.llvm-filecheck".format(build_triple), value, config) + elif option.name == "tools": + set("build.tools", value.split(","), config) + elif option.name == "bootstrap-cache-path": + set("build.bootstrap-cache-path", value, config) + elif option.name == "codegen-backends": + set("rust.codegen-backends", value.split(","), config) + elif option.name == "host": + set("build.host", value.split(","), config) + elif option.name == "target": + set("build.target", value.split(","), config) + elif option.name == "full-tools": + set("rust.codegen-backends", ["llvm"], config) + set("rust.lld", True, config) + set("rust.llvm-tools", True, config) + set("rust.llvm-bitcode-linker", True, config) + set("build.extended", True, config) + elif option.name in ["option-checking", "verbose-configure"]: # this was handled above pass - elif option.name == 'dist-compression-formats': - set('dist.compression-formats', value.split(','), config) + elif option.name == "dist-compression-formats": + set("dist.compression-formats", value.split(","), config) else: raise RuntimeError("unhandled option {}".format(option.name)) + # "Parse" the `config.example.toml` file into the various sections, and we'll # use this as a template of a `config.toml` to write out which preserves # all the various comments and whatnot. @@ -406,20 +567,22 @@ def parse_example_config(known_args, config): targets = {} top_level_keys = [] - with open(rust_dir + '/config.example.toml') as example_config: + with open(rust_dir + "/config.example.toml") as example_config: example_lines = example_config.read().split("\n") for line in example_lines: if cur_section is None: - if line.count('=') == 1: - top_level_key = line.split('=')[0] - top_level_key = top_level_key.strip(' #') + if line.count("=") == 1: + top_level_key = line.split("=")[0] + top_level_key = top_level_key.strip(" #") top_level_keys.append(top_level_key) - if line.startswith('['): + if line.startswith("["): cur_section = line[1:-1] - if cur_section.startswith('target'): - cur_section = 'target' - elif '.' in cur_section: - raise RuntimeError("don't know how to deal with section: {}".format(cur_section)) + if cur_section.startswith("target"): + cur_section = "target" + elif "." in cur_section: + raise RuntimeError( + "don't know how to deal with section: {}".format(cur_section) + ) sections[cur_section] = [line] section_order.append(cur_section) else: @@ -428,22 +591,25 @@ def parse_example_config(known_args, config): # Fill out the `targets` array by giving all configured targets a copy of the # `target` section we just loaded from the example config configured_targets = [build(known_args)] - if 'build' in config: - if 'host' in config['build']: - configured_targets += config['build']['host'] - if 'target' in config['build']: - configured_targets += config['build']['target'] - if 'target' in config: - for target in config['target']: + if "build" in config: + if "host" in config["build"]: + configured_targets += config["build"]["host"] + if "target" in config["build"]: + configured_targets += config["build"]["target"] + if "target" in config: + for target in config["target"]: configured_targets.append(target) for target in configured_targets: - targets[target] = sections['target'][:] + targets[target] = sections["target"][:] # For `.` to be valid TOML, it needs to be quoted. But `bootstrap.py` doesn't use a proper TOML parser and fails to parse the target. # Avoid using quotes unless it's necessary. - targets[target][0] = targets[target][0].replace("x86_64-unknown-linux-gnu", "'{}'".format(target) if "." in target else target) + targets[target][0] = targets[target][0].replace( + "x86_64-unknown-linux-gnu", + "'{}'".format(target) if "." in target else target, + ) - if 'profile' not in config: - set('profile', 'dist', config) + if "profile" not in config: + set("profile", "dist", config) configure_file(sections, top_level_keys, targets, config) return section_order, sections, targets @@ -467,7 +633,7 @@ def to_toml(value): else: return "false" elif isinstance(value, list): - return '[' + ', '.join(map(to_toml, value)) + ']' + return "[" + ", ".join(map(to_toml, value)) + "]" elif isinstance(value, str): # Don't put quotes around numeric values if is_number(value): @@ -475,9 +641,18 @@ def to_toml(value): else: return "'" + value + "'" elif isinstance(value, dict): - return "{" + ", ".join(map(lambda a: "{} = {}".format(to_toml(a[0]), to_toml(a[1])), value.items())) + "}" + return ( + "{" + + ", ".join( + map( + lambda a: "{} = {}".format(to_toml(a[0]), to_toml(a[1])), + value.items(), + ) + ) + + "}" + ) else: - raise RuntimeError('no toml') + raise RuntimeError("no toml") def configure_section(lines, config): @@ -485,7 +660,7 @@ def configure_section(lines, config): value = config[key] found = False for i, line in enumerate(lines): - if not line.startswith('#' + key + ' = '): + if not line.startswith("#" + key + " = "): continue found = True lines[i] = "{} = {}".format(key, to_toml(value)) @@ -501,7 +676,9 @@ def configure_section(lines, config): def configure_top_level_key(lines, top_level_key, value): for i, line in enumerate(lines): - if line.startswith('#' + top_level_key + ' = ') or line.startswith(top_level_key + ' = '): + if line.startswith("#" + top_level_key + " = ") or line.startswith( + top_level_key + " = " + ): lines[i] = "{} = {}".format(top_level_key, to_toml(value)) return @@ -512,11 +689,13 @@ def configure_top_level_key(lines, top_level_key, value): def configure_file(sections, top_level_keys, targets, config): for section_key, section_config in config.items(): if section_key not in sections and section_key not in top_level_keys: - raise RuntimeError("config key {} not in sections or top_level_keys".format(section_key)) + raise RuntimeError( + "config key {} not in sections or top_level_keys".format(section_key) + ) if section_key in top_level_keys: configure_top_level_key(sections[None], section_key, section_config) - elif section_key == 'target': + elif section_key == "target": for target in section_config: configure_section(targets[target], section_config[target]) else: @@ -536,18 +715,19 @@ def write_uncommented(target, f): block = [] is_comment = True continue - is_comment = is_comment and line.startswith('#') + is_comment = is_comment and line.startswith("#") return f def write_config_toml(writer, section_order, targets, sections): for section in section_order: - if section == 'target': + if section == "target": for target in targets: writer = write_uncommented(targets[target], writer) else: writer = write_uncommented(sections[section], writer) + def quit_if_file_exists(file): if os.path.isfile(file): msg = "Existing '{}' detected. Exiting".format(file) @@ -559,9 +739,10 @@ def quit_if_file_exists(file): err(msg) + if __name__ == "__main__": # If 'config.toml' already exists, exit the script at this point - quit_if_file_exists('config.toml') + quit_if_file_exists("config.toml") if "GITHUB_ACTIONS" in os.environ: print("::group::Configure the build") @@ -575,13 +756,13 @@ if __name__ == "__main__": # order that we read it in. p("") p("writing `config.toml` in current directory") - with bootstrap.output('config.toml') as f: + with bootstrap.output("config.toml") as f: write_config_toml(f, section_order, targets, sections) - with bootstrap.output('Makefile') as f: - contents = os.path.join(rust_dir, 'src', 'bootstrap', 'mk', 'Makefile.in') + with bootstrap.output("Makefile") as f: + contents = os.path.join(rust_dir, "src", "bootstrap", "mk", "Makefile.in") contents = open(contents).read() - contents = contents.replace("$(CFG_SRC_DIR)", rust_dir + '/') + contents = contents.replace("$(CFG_SRC_DIR)", rust_dir + "/") contents = contents.replace("$(CFG_PYTHON)", sys.executable) f.write(contents) diff --git a/src/ci/cpu-usage-over-time.py b/src/ci/cpu-usage-over-time.py index adfd895ead0..3d9dc86734f 100755 --- a/src/ci/cpu-usage-over-time.py +++ b/src/ci/cpu-usage-over-time.py @@ -40,12 +40,13 @@ import time # Python 3.3 changed the value of `sys.platform` on Linux from "linux2" to just # "linux". We check here with `.startswith` to keep compatibility with older # Python versions (especially Python 2.7). -if sys.platform.startswith('linux'): +if sys.platform.startswith("linux"): + class State: def __init__(self): - with open('/proc/stat', 'r') as file: + with open("/proc/stat", "r") as file: data = file.readline().split() - if data[0] != 'cpu': + if data[0] != "cpu": raise Exception('did not start with "cpu"') self.user = int(data[1]) self.nice = int(data[2]) @@ -69,10 +70,21 @@ if sys.platform.startswith('linux'): steal = self.steal - prev.steal guest = self.guest - prev.guest guest_nice = self.guest_nice - prev.guest_nice - total = user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice + total = ( + user + + nice + + system + + idle + + iowait + + irq + + softirq + + steal + + guest + + guest_nice + ) return float(idle) / float(total) * 100 -elif sys.platform == 'win32': +elif sys.platform == "win32": from ctypes.wintypes import DWORD from ctypes import Structure, windll, WinError, GetLastError, byref @@ -104,9 +116,10 @@ elif sys.platform == 'win32': kernel = self.kernel - prev.kernel return float(idle) / float(user + kernel) * 100 -elif sys.platform == 'darwin': +elif sys.platform == "darwin": from ctypes import * - libc = cdll.LoadLibrary('/usr/lib/libc.dylib') + + libc = cdll.LoadLibrary("/usr/lib/libc.dylib") class host_cpu_load_info_data_t(Structure): _fields_ = [("cpu_ticks", c_uint * 4)] @@ -116,7 +129,7 @@ elif sys.platform == 'darwin': c_uint, c_int, POINTER(host_cpu_load_info_data_t), - POINTER(c_int) + POINTER(c_int), ] host_statistics.restype = c_int @@ -124,13 +137,14 @@ elif sys.platform == 'darwin': CPU_STATE_SYSTEM = 1 CPU_STATE_IDLE = 2 CPU_STATE_NICE = 3 + class State: def __init__(self): stats = host_cpu_load_info_data_t() - count = c_int(4) # HOST_CPU_LOAD_INFO_COUNT + count = c_int(4) # HOST_CPU_LOAD_INFO_COUNT err = libc.host_statistics( libc.mach_host_self(), - c_int(3), # HOST_CPU_LOAD_INFO + c_int(3), # HOST_CPU_LOAD_INFO byref(stats), byref(count), ) @@ -148,7 +162,7 @@ elif sys.platform == 'darwin': return float(idle) / float(user + system + idle + nice) * 100.0 else: - print('unknown platform', sys.platform) + print("unknown platform", sys.platform) sys.exit(1) cur_state = State() diff --git a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py index 3577643ca55..4f877389fbc 100755 --- a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py +++ b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py @@ -8,78 +8,79 @@ import tempfile from pathlib import Path -TARGET_AARCH64 = 'aarch64-unknown-uefi' -TARGET_I686 = 'i686-unknown-uefi' -TARGET_X86_64 = 'x86_64-unknown-uefi' +TARGET_AARCH64 = "aarch64-unknown-uefi" +TARGET_I686 = "i686-unknown-uefi" +TARGET_X86_64 = "x86_64-unknown-uefi" + def run(*cmd, capture=False, check=True, env=None, timeout=None): """Print and run a command, optionally capturing the output.""" cmd = [str(p) for p in cmd] - print(' '.join(cmd)) - return subprocess.run(cmd, - capture_output=capture, - check=check, - env=env, - text=True, - timeout=timeout) + print(" ".join(cmd)) + return subprocess.run( + cmd, capture_output=capture, check=check, env=env, text=True, timeout=timeout + ) + def build_and_run(tmp_dir, target): if target == TARGET_AARCH64: - boot_file_name = 'bootaa64.efi' - ovmf_dir = Path('/usr/share/AAVMF') - ovmf_code = 'AAVMF_CODE.fd' - ovmf_vars = 'AAVMF_VARS.fd' - qemu = 'qemu-system-aarch64' - machine = 'virt' - cpu = 'cortex-a72' + boot_file_name = "bootaa64.efi" + ovmf_dir = Path("/usr/share/AAVMF") + ovmf_code = "AAVMF_CODE.fd" + ovmf_vars = "AAVMF_VARS.fd" + qemu = "qemu-system-aarch64" + machine = "virt" + cpu = "cortex-a72" elif target == TARGET_I686: - boot_file_name = 'bootia32.efi' - ovmf_dir = Path('/usr/share/OVMF') - ovmf_code = 'OVMF32_CODE_4M.secboot.fd' - ovmf_vars = 'OVMF32_VARS_4M.fd' + boot_file_name = "bootia32.efi" + ovmf_dir = Path("/usr/share/OVMF") + ovmf_code = "OVMF32_CODE_4M.secboot.fd" + ovmf_vars = "OVMF32_VARS_4M.fd" # The i686 target intentionally uses 64-bit qemu; the important # difference is that the OVMF code provides a 32-bit environment. - qemu = 'qemu-system-x86_64' - machine = 'q35' - cpu = 'qemu64' + qemu = "qemu-system-x86_64" + machine = "q35" + cpu = "qemu64" elif target == TARGET_X86_64: - boot_file_name = 'bootx64.efi' - ovmf_dir = Path('/usr/share/OVMF') - ovmf_code = 'OVMF_CODE.fd' - ovmf_vars = 'OVMF_VARS.fd' - qemu = 'qemu-system-x86_64' - machine = 'q35' - cpu = 'qemu64' + boot_file_name = "bootx64.efi" + ovmf_dir = Path("/usr/share/OVMF") + ovmf_code = "OVMF_CODE.fd" + ovmf_vars = "OVMF_VARS.fd" + qemu = "qemu-system-x86_64" + machine = "q35" + cpu = "qemu64" else: - raise KeyError('invalid target') + raise KeyError("invalid target") - host_artifacts = Path('/checkout/obj/build/x86_64-unknown-linux-gnu') - stage0 = host_artifacts / 'stage0/bin' - stage2 = host_artifacts / 'stage2/bin' + host_artifacts = Path("/checkout/obj/build/x86_64-unknown-linux-gnu") + stage0 = host_artifacts / "stage0/bin" + stage2 = host_artifacts / "stage2/bin" env = dict(os.environ) - env['PATH'] = '{}:{}:{}'.format(stage2, stage0, env['PATH']) + env["PATH"] = "{}:{}:{}".format(stage2, stage0, env["PATH"]) # Copy the test create into `tmp_dir`. - test_crate = Path(tmp_dir) / 'uefi_qemu_test' - shutil.copytree('/uefi_qemu_test', test_crate) + test_crate = Path(tmp_dir) / "uefi_qemu_test" + shutil.copytree("/uefi_qemu_test", test_crate) # Build the UEFI executable. - run('cargo', - 'build', - '--manifest-path', - test_crate / 'Cargo.toml', - '--target', + run( + "cargo", + "build", + "--manifest-path", + test_crate / "Cargo.toml", + "--target", target, - env=env) + env=env, + ) # Create a mock EFI System Partition in a subdirectory. - esp = test_crate / 'esp' - boot = esp / 'efi/boot' + esp = test_crate / "esp" + boot = esp / "efi/boot" os.makedirs(boot, exist_ok=True) # Copy the executable into the ESP. - src_exe_path = test_crate / 'target' / target / 'debug/uefi_qemu_test.efi' + src_exe_path = test_crate / "target" / target / "debug/uefi_qemu_test.efi" shutil.copy(src_exe_path, boot / boot_file_name) print(src_exe_path, boot / boot_file_name) @@ -89,37 +90,39 @@ def build_and_run(tmp_dir, target): # Make a writable copy of the vars file. aarch64 doesn't boot # correctly with read-only vars. - ovmf_rw_vars = Path(tmp_dir) / 'vars.fd' + ovmf_rw_vars = Path(tmp_dir) / "vars.fd" shutil.copy(ovmf_vars, ovmf_rw_vars) # Run the executable in QEMU and capture the output. - output = run(qemu, - '-machine', - machine, - '-cpu', - cpu, - '-display', - 'none', - '-serial', - 'stdio', - '-drive', - f'if=pflash,format=raw,readonly=on,file={ovmf_code}', - '-drive', - f'if=pflash,format=raw,readonly=off,file={ovmf_rw_vars}', - '-drive', - f'format=raw,file=fat:rw:{esp}', - capture=True, - check=True, - # Set a timeout to kill the VM in case something goes wrong. - timeout=60).stdout - - if 'Hello World!' in output: - print('VM produced expected output') + output = run( + qemu, + "-machine", + machine, + "-cpu", + cpu, + "-display", + "none", + "-serial", + "stdio", + "-drive", + f"if=pflash,format=raw,readonly=on,file={ovmf_code}", + "-drive", + f"if=pflash,format=raw,readonly=off,file={ovmf_rw_vars}", + "-drive", + f"format=raw,file=fat:rw:{esp}", + capture=True, + check=True, + # Set a timeout to kill the VM in case something goes wrong. + timeout=60, + ).stdout + + if "Hello World!" in output: + print("VM produced expected output") else: - print('unexpected VM output:') - print('---start---') + print("unexpected VM output:") + print("---start---") print(output) - print('---end---') + print("---end---") sys.exit(1) diff --git a/src/ci/docker/scripts/android-sdk-manager.py b/src/ci/docker/scripts/android-sdk-manager.py index 66cba58427b..6356f15a886 100755 --- a/src/ci/docker/scripts/android-sdk-manager.py +++ b/src/ci/docker/scripts/android-sdk-manager.py @@ -35,6 +35,7 @@ MIRROR_BUCKET = "rust-lang-ci-mirrors" MIRROR_BUCKET_REGION = "us-west-1" MIRROR_BASE_DIR = "rustc/android/" + class Package: def __init__(self, path, url, sha1, deps=None): if deps is None: @@ -53,18 +54,25 @@ class Package: sha1 = hashlib.sha1(f.read()).hexdigest() if sha1 != self.sha1: raise RuntimeError( - "hash mismatch for package " + self.path + ": " + - sha1 + " vs " + self.sha1 + " (known good)" + "hash mismatch for package " + + self.path + + ": " + + sha1 + + " vs " + + self.sha1 + + " (known good)" ) return file def __repr__(self): - return " Optional[WorkflowRunType]: try_build = ctx.ref in ( "refs/heads/try", "refs/heads/try-perf", - "refs/heads/automation/bors/try" + "refs/heads/automation/bors/try", ) # Unrolled branch from a rollup for testing perf @@ -135,11 +136,15 @@ def calculate_jobs(run_type: WorkflowRunType, job_data: Dict[str, Any]) -> List[ continue jobs.append(job[0]) if unknown_jobs: - raise Exception(f"Custom job(s) `{unknown_jobs}` not found in auto jobs") + raise Exception( + f"Custom job(s) `{unknown_jobs}` not found in auto jobs" + ) return add_base_env(name_jobs(jobs, "try"), job_data["envs"]["try"]) elif isinstance(run_type, AutoRunType): - return add_base_env(name_jobs(job_data["auto"], "auto"), job_data["envs"]["auto"]) + return add_base_env( + name_jobs(job_data["auto"], "auto"), job_data["envs"]["auto"] + ) return [] @@ -161,7 +166,7 @@ def get_github_ctx() -> GitHubCtx: event_name=event_name, ref=os.environ["GITHUB_REF"], repository=os.environ["GITHUB_REPOSITORY"], - commit_message=commit_message + commit_message=commit_message, ) diff --git a/src/ci/scripts/upload-build-metrics.py b/src/ci/scripts/upload-build-metrics.py index a95e0949d70..23061884a39 100644 --- a/src/ci/scripts/upload-build-metrics.py +++ b/src/ci/scripts/upload-build-metrics.py @@ -19,6 +19,7 @@ $ python3 upload-build-metrics.py `path-to-CPU-usage-CSV` is a path to a CSV generated by the `src/ci/cpu-usage-over-time.py` script. """ + import argparse import csv import os @@ -31,7 +32,7 @@ from typing import List def load_cpu_usage(path: Path) -> List[float]: usage = [] with open(path) as f: - reader = csv.reader(f, delimiter=',') + reader = csv.reader(f, delimiter=",") for row in reader: # The log might contain incomplete rows or some Python exception if len(row) == 2: @@ -50,25 +51,21 @@ def upload_datadog_measure(name: str, value: float): print(f"Metric {name}: {value:.4f}") datadog_cmd = "datadog-ci" - if os.getenv("GITHUB_ACTIONS") is not None and sys.platform.lower().startswith("win"): + if os.getenv("GITHUB_ACTIONS") is not None and sys.platform.lower().startswith( + "win" + ): # Due to weird interaction of MSYS2 and Python, we need to use an absolute path, # and also specify the ".cmd" at the end. See https://github.com/rust-lang/rust/pull/125771. datadog_cmd = "C:\\npm\\prefix\\datadog-ci.cmd" - subprocess.run([ - datadog_cmd, - "measure", - "--level", "job", - "--measures", f"{name}:{value}" - ], - check=False + subprocess.run( + [datadog_cmd, "measure", "--level", "job", "--measures", f"{name}:{value}"], + check=False, ) if __name__ == "__main__": - parser = argparse.ArgumentParser( - prog="DataDog metric uploader" - ) + parser = argparse.ArgumentParser(prog="DataDog metric uploader") parser.add_argument("cpu-usage-history-csv") args = parser.parse_args() diff --git a/src/etc/dec2flt_table.py b/src/etc/dec2flt_table.py index 9264a8439bb..791186de9c1 100755 --- a/src/etc/dec2flt_table.py +++ b/src/etc/dec2flt_table.py @@ -13,6 +13,7 @@ i.e., within 0.5 ULP of the true value. Adapted from Daniel Lemire's fast_float ``table_generation.py``, available here: . """ + from __future__ import print_function from math import ceil, floor, log from collections import deque @@ -34,6 +35,7 @@ STATIC_WARNING = """ // the final binary. """ + def main(): min_exp = minimum_exponent(10) max_exp = maximum_exponent(10) @@ -41,10 +43,10 @@ def main(): print(HEADER.strip()) print() - print('pub const SMALLEST_POWER_OF_FIVE: i32 = {};'.format(min_exp)) - print('pub const LARGEST_POWER_OF_FIVE: i32 = {};'.format(max_exp)) - print('pub const N_POWERS_OF_FIVE: usize = ', end='') - print('(LARGEST_POWER_OF_FIVE - SMALLEST_POWER_OF_FIVE + 1) as usize;') + print("pub const SMALLEST_POWER_OF_FIVE: i32 = {};".format(min_exp)) + print("pub const LARGEST_POWER_OF_FIVE: i32 = {};".format(max_exp)) + print("pub const N_POWERS_OF_FIVE: usize = ", end="") + print("(LARGEST_POWER_OF_FIVE - SMALLEST_POWER_OF_FIVE + 1) as usize;") print() print_proper_powers(min_exp, max_exp, bias) @@ -54,7 +56,7 @@ def minimum_exponent(base): def maximum_exponent(base): - return floor(log(1.7976931348623157e+308, base)) + return floor(log(1.7976931348623157e308, base)) def print_proper_powers(min_exp, max_exp, bias): @@ -64,46 +66,46 @@ def print_proper_powers(min_exp, max_exp, bias): # 2^(2b)/(5^−q) with b=64 + int(math.ceil(log2(5^−q))) powers = [] for q in range(min_exp, 0): - power5 = 5 ** -q + power5 = 5**-q z = 0 while (1 << z) < power5: z += 1 if q >= -27: b = z + 127 - c = 2 ** b // power5 + 1 + c = 2**b // power5 + 1 powers.append((c, q)) else: b = 2 * z + 2 * 64 - c = 2 ** b // power5 + 1 + c = 2**b // power5 + 1 # truncate - while c >= (1<<128): + while c >= (1 << 128): c //= 2 powers.append((c, q)) # Add positive exponents for q in range(0, max_exp + 1): - power5 = 5 ** q + power5 = 5**q # move the most significant bit in position - while power5 < (1<<127): + while power5 < (1 << 127): power5 *= 2 # *truncate* - while power5 >= (1<<128): + while power5 >= (1 << 128): power5 //= 2 powers.append((power5, q)) # Print the powers. print(STATIC_WARNING.strip()) - print('#[rustfmt::skip]') - typ = '[(u64, u64); N_POWERS_OF_FIVE]' - print('pub static POWER_OF_FIVE_128: {} = ['.format(typ)) + print("#[rustfmt::skip]") + typ = "[(u64, u64); N_POWERS_OF_FIVE]" + print("pub static POWER_OF_FIVE_128: {} = [".format(typ)) for c, exp in powers: - hi = '0x{:x}'.format(c // (1 << 64)) - lo = '0x{:x}'.format(c % (1 << 64)) - value = ' ({}, {}), '.format(hi, lo) - comment = '// {}^{}'.format(5, exp) - print(value.ljust(46, ' ') + comment) - print('];') + hi = "0x{:x}".format(c // (1 << 64)) + lo = "0x{:x}".format(c % (1 << 64)) + value = " ({}, {}), ".format(hi, lo) + comment = "// {}^{}".format(5, exp) + print(value.ljust(46, " ") + comment) + print("];") -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/src/etc/gdb_load_rust_pretty_printers.py b/src/etc/gdb_load_rust_pretty_printers.py index e05039ce474..73d1e79f961 100644 --- a/src/etc/gdb_load_rust_pretty_printers.py +++ b/src/etc/gdb_load_rust_pretty_printers.py @@ -1,6 +1,7 @@ # Add this folder to the python sys path; GDB Python-interpreter will now find modules in this path import sys from os import path + self_dir = path.dirname(path.realpath(__file__)) sys.path.append(self_dir) diff --git a/src/etc/gdb_lookup.py b/src/etc/gdb_lookup.py index f3ac9c10978..d368f7ed1ec 100644 --- a/src/etc/gdb_lookup.py +++ b/src/etc/gdb_lookup.py @@ -6,8 +6,11 @@ from gdb_providers import * from rust_types import * -_gdb_version_matched = re.search('([0-9]+)\\.([0-9]+)', gdb.VERSION) -gdb_version = [int(num) for num in _gdb_version_matched.groups()] if _gdb_version_matched else [] +_gdb_version_matched = re.search("([0-9]+)\\.([0-9]+)", gdb.VERSION) +gdb_version = ( + [int(num) for num in _gdb_version_matched.groups()] if _gdb_version_matched else [] +) + def register_printers(objfile): objfile.pretty_printers.append(printer) diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py index e8f9dee07d3..34bb5c39909 100644 --- a/src/etc/gdb_providers.py +++ b/src/etc/gdb_providers.py @@ -21,7 +21,7 @@ def unwrap_unique_or_non_null(unique_or_nonnull): # GDB 14 has a tag class that indicates that extension methods are ok # to call. Use of this tag only requires that printers hide local # attributes and methods by prefixing them with "_". -if hasattr(gdb, 'ValuePrinter'): +if hasattr(gdb, "ValuePrinter"): printer_base = gdb.ValuePrinter else: printer_base = object @@ -98,7 +98,7 @@ class StdStrProvider(printer_base): def _enumerate_array_elements(element_ptrs): - for (i, element_ptr) in enumerate(element_ptrs): + for i, element_ptr in enumerate(element_ptrs): key = "[{}]".format(i) element = element_ptr.dereference() @@ -173,7 +173,8 @@ class StdVecDequeProvider(printer_base): def children(self): return _enumerate_array_elements( - (self._data_ptr + ((self._head + index) % self._cap)) for index in xrange(self._size) + (self._data_ptr + ((self._head + index) % self._cap)) + for index in xrange(self._size) ) @staticmethod @@ -270,7 +271,9 @@ def children_of_btree_map(map): # Yields each key/value pair in the node and in any child nodes. def children_of_node(node_ptr, height): def cast_to_internal(node): - internal_type_name = node.type.target().name.replace("LeafNode", "InternalNode", 1) + internal_type_name = node.type.target().name.replace( + "LeafNode", "InternalNode", 1 + ) internal_type = gdb.lookup_type(internal_type_name) return node.cast(internal_type.pointer()) @@ -293,8 +296,16 @@ def children_of_btree_map(map): # Avoid "Cannot perform pointer math on incomplete type" on zero-sized arrays. key_type_size = keys.type.sizeof val_type_size = vals.type.sizeof - key = keys[i]["value"]["value"] if key_type_size > 0 else gdb.parse_and_eval("()") - val = vals[i]["value"]["value"] if val_type_size > 0 else gdb.parse_and_eval("()") + key = ( + keys[i]["value"]["value"] + if key_type_size > 0 + else gdb.parse_and_eval("()") + ) + val = ( + vals[i]["value"]["value"] + if val_type_size > 0 + else gdb.parse_and_eval("()") + ) yield key, val if map["length"] > 0: @@ -352,7 +363,7 @@ class StdOldHashMapProvider(printer_base): self._hashes = self._table["hashes"] self._hash_uint_type = self._hashes.type self._hash_uint_size = self._hashes.type.sizeof - self._modulo = 2 ** self._hash_uint_size + self._modulo = 2**self._hash_uint_size self._data_ptr = self._hashes[ZERO_FIELD]["pointer"] self._capacity_mask = int(self._table["capacity_mask"]) @@ -382,8 +393,14 @@ class StdOldHashMapProvider(printer_base): hashes = self._hash_uint_size * self._capacity align = self._pair_type_size - len_rounded_up = (((((hashes + align) % self._modulo - 1) % self._modulo) & ~( - (align - 1) % self._modulo)) % self._modulo - hashes) % self._modulo + len_rounded_up = ( + ( + (((hashes + align) % self._modulo - 1) % self._modulo) + & ~((align - 1) % self._modulo) + ) + % self._modulo + - hashes + ) % self._modulo pairs_offset = hashes + len_rounded_up pairs_start = gdb.Value(start + pairs_offset).cast(self._pair_type.pointer()) diff --git a/src/etc/generate-deriving-span-tests.py b/src/etc/generate-deriving-span-tests.py index d61693460bc..2e810d7df97 100755 --- a/src/etc/generate-deriving-span-tests.py +++ b/src/etc/generate-deriving-span-tests.py @@ -12,7 +12,8 @@ import os import stat TEST_DIR = os.path.abspath( - os.path.join(os.path.dirname(__file__), '../test/ui/derives/')) + os.path.join(os.path.dirname(__file__), "../test/ui/derives/") +) TEMPLATE = """\ // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' @@ -56,28 +57,33 @@ ENUM_TUPLE, ENUM_STRUCT, STRUCT_FIELDS, STRUCT_TUPLE = range(4) def create_test_case(type, trait, super_traits, error_count): - string = [ENUM_STRING, ENUM_STRUCT_VARIANT_STRING, STRUCT_STRING, STRUCT_TUPLE_STRING][type] - all_traits = ','.join([trait] + super_traits) - super_traits = ','.join(super_traits) - error_deriving = '#[derive(%s)]' % super_traits if super_traits else '' - - errors = '\n'.join('//~%s ERROR' % ('^' * n) for n in range(error_count)) + string = [ + ENUM_STRING, + ENUM_STRUCT_VARIANT_STRING, + STRUCT_STRING, + STRUCT_TUPLE_STRING, + ][type] + all_traits = ",".join([trait] + super_traits) + super_traits = ",".join(super_traits) + error_deriving = "#[derive(%s)]" % super_traits if super_traits else "" + + errors = "\n".join("//~%s ERROR" % ("^" * n) for n in range(error_count)) code = string.format(traits=all_traits, errors=errors) return TEMPLATE.format(error_deriving=error_deriving, code=code) def write_file(name, string): - test_file = os.path.join(TEST_DIR, 'derives-span-%s.rs' % name) + test_file = os.path.join(TEST_DIR, "derives-span-%s.rs" % name) # set write permission if file exists, so it can be changed if os.path.exists(test_file): os.chmod(test_file, stat.S_IWUSR) - with open(test_file, 'w') as f: + with open(test_file, "w") as f: f.write(string) # mark file read-only - os.chmod(test_file, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH) + os.chmod(test_file, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH) ENUM = 1 @@ -85,29 +91,31 @@ STRUCT = 2 ALL = STRUCT | ENUM traits = { - 'Default': (STRUCT, [], 1), - 'FromPrimitive': (0, [], 0), # only works for C-like enums - - 'Decodable': (0, [], 0), # FIXME: quoting gives horrible spans - 'Encodable': (0, [], 0), # FIXME: quoting gives horrible spans + "Default": (STRUCT, [], 1), + "FromPrimitive": (0, [], 0), # only works for C-like enums + "Decodable": (0, [], 0), # FIXME: quoting gives horrible spans + "Encodable": (0, [], 0), # FIXME: quoting gives horrible spans } -for (trait, supers, errs) in [('Clone', [], 1), - ('PartialEq', [], 2), - ('PartialOrd', ['PartialEq'], 1), - ('Eq', ['PartialEq'], 1), - ('Ord', ['Eq', 'PartialOrd', 'PartialEq'], 1), - ('Debug', [], 1), - ('Hash', [], 1)]: +for trait, supers, errs in [ + ("Clone", [], 1), + ("PartialEq", [], 2), + ("PartialOrd", ["PartialEq"], 1), + ("Eq", ["PartialEq"], 1), + ("Ord", ["Eq", "PartialOrd", "PartialEq"], 1), + ("Debug", [], 1), + ("Hash", [], 1), +]: traits[trait] = (ALL, supers, errs) -for (trait, (types, super_traits, error_count)) in traits.items(): +for trait, (types, super_traits, error_count) in traits.items(): + def mk(ty, t=trait, st=super_traits, ec=error_count): return create_test_case(ty, t, st, ec) if types & ENUM: - write_file(trait + '-enum', mk(ENUM_TUPLE)) - write_file(trait + '-enum-struct-variant', mk(ENUM_STRUCT)) + write_file(trait + "-enum", mk(ENUM_TUPLE)) + write_file(trait + "-enum-struct-variant", mk(ENUM_STRUCT)) if types & STRUCT: - write_file(trait + '-struct', mk(STRUCT_FIELDS)) - write_file(trait + '-tuple-struct', mk(STRUCT_TUPLE)) + write_file(trait + "-struct", mk(STRUCT_FIELDS)) + write_file(trait + "-tuple-struct", mk(STRUCT_TUPLE)) diff --git a/src/etc/generate-keyword-tests.py b/src/etc/generate-keyword-tests.py index 77c3d2758c6..28f932acd9d 100755 --- a/src/etc/generate-keyword-tests.py +++ b/src/etc/generate-keyword-tests.py @@ -22,18 +22,16 @@ fn main() { } """ -test_dir = os.path.abspath( - os.path.join(os.path.dirname(__file__), '../test/ui/parser') -) +test_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "../test/ui/parser")) for kw in sys.argv[1:]: - test_file = os.path.join(test_dir, 'keyword-%s-as-identifier.rs' % kw) + test_file = os.path.join(test_dir, "keyword-%s-as-identifier.rs" % kw) # set write permission if file exists, so it can be changed if os.path.exists(test_file): os.chmod(test_file, stat.S_IWUSR) - with open(test_file, 'wt') as f: + with open(test_file, "wt") as f: f.write(template % (kw, kw, kw)) # mark file read-only diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py index 851b01a7458..d6b594aca71 100755 --- a/src/etc/htmldocck.py +++ b/src/etc/htmldocck.py @@ -127,6 +127,7 @@ import os.path import re import shlex from collections import namedtuple + try: from html.parser import HTMLParser except ImportError: @@ -142,12 +143,28 @@ except ImportError: from htmlentitydefs import name2codepoint # "void elements" (no closing tag) from the HTML Standard section 12.1.2 -VOID_ELEMENTS = {'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', - 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'} +VOID_ELEMENTS = { + "area", + "base", + "br", + "col", + "embed", + "hr", + "img", + "input", + "keygen", + "link", + "menuitem", + "meta", + "param", + "source", + "track", + "wbr", +} # Python 2 -> 3 compatibility try: - unichr # noqa: B018 FIXME: py2 + unichr # noqa: B018 FIXME: py2 except NameError: unichr = chr @@ -158,18 +175,20 @@ channel = os.environ["DOC_RUST_LANG_ORG_CHANNEL"] rust_test_path = None bless = None + class CustomHTMLParser(HTMLParser): """simplified HTML parser. this is possible because we are dealing with very regular HTML from rustdoc; we only have to deal with i) void elements and ii) empty attributes.""" + def __init__(self, target=None): HTMLParser.__init__(self) self.__builder = target or ET.TreeBuilder() def handle_starttag(self, tag, attrs): - attrs = {k: v or '' for k, v in attrs} + attrs = {k: v or "" for k, v in attrs} self.__builder.start(tag, attrs) if tag in VOID_ELEMENTS: self.__builder.end(tag) @@ -178,7 +197,7 @@ class CustomHTMLParser(HTMLParser): self.__builder.end(tag) def handle_startendtag(self, tag, attrs): - attrs = {k: v or '' for k, v in attrs} + attrs = {k: v or "" for k, v in attrs} self.__builder.start(tag, attrs) self.__builder.end(tag) @@ -189,7 +208,7 @@ class CustomHTMLParser(HTMLParser): self.__builder.data(unichr(name2codepoint[name])) def handle_charref(self, name): - code = int(name[1:], 16) if name.startswith(('x', 'X')) else int(name, 10) + code = int(name[1:], 16) if name.startswith(("x", "X")) else int(name, 10) self.__builder.data(unichr(code)) def close(self): @@ -197,7 +216,7 @@ class CustomHTMLParser(HTMLParser): return self.__builder.close() -Command = namedtuple('Command', 'negated cmd args lineno context') +Command = namedtuple("Command", "negated cmd args lineno context") class FailedCheck(Exception): @@ -216,17 +235,17 @@ def concat_multi_lines(f): concatenated.""" lastline = None # set to the last line when the last line has a backslash firstlineno = None - catenated = '' + catenated = "" for lineno, line in enumerate(f): - line = line.rstrip('\r\n') + line = line.rstrip("\r\n") # strip the common prefix from the current line if needed if lastline is not None: common_prefix = os.path.commonprefix([line, lastline]) - line = line[len(common_prefix):].lstrip() + line = line[len(common_prefix) :].lstrip() firstlineno = firstlineno or lineno - if line.endswith('\\'): + if line.endswith("\\"): if lastline is None: lastline = line[:-1] catenated += line[:-1] @@ -234,10 +253,10 @@ def concat_multi_lines(f): yield firstlineno, catenated + line lastline = None firstlineno = None - catenated = '' + catenated = "" if lastline is not None: - print_err(lineno, line, 'Trailing backslash at the end of the file') + print_err(lineno, line, "Trailing backslash at the end of the file") def get_known_directive_names(): @@ -253,12 +272,12 @@ def get_known_directive_names(): "tools/compiletest/src/directive-list.rs", ), "r", - encoding="utf8" + encoding="utf8", ) as fd: content = fd.read() return [ - line.strip().replace('",', '').replace('"', '') - for line in content.split('\n') + line.strip().replace('",', "").replace('"', "") + for line in content.split("\n") if filter_line(line) ] @@ -269,35 +288,42 @@ def get_known_directive_names(): # See . KNOWN_DIRECTIVE_NAMES = get_known_directive_names() -LINE_PATTERN = re.compile(r''' +LINE_PATTERN = re.compile( + r""" //@\s+ (?P!?)(?P[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*) (?P.*)$ -''', re.X | re.UNICODE) +""", + re.X | re.UNICODE, +) def get_commands(template): - with io.open(template, encoding='utf-8') as f: + with io.open(template, encoding="utf-8") as f: for lineno, line in concat_multi_lines(f): m = LINE_PATTERN.search(line) if not m: continue - cmd = m.group('cmd') - negated = (m.group('negated') == '!') + cmd = m.group("cmd") + negated = m.group("negated") == "!" if not negated and cmd in KNOWN_DIRECTIVE_NAMES: continue - args = m.group('args') + args = m.group("args") if args and not args[:1].isspace(): - print_err(lineno, line, 'Invalid template syntax') + print_err(lineno, line, "Invalid template syntax") continue try: args = shlex.split(args) except UnicodeEncodeError: - args = [arg.decode('utf-8') for arg in shlex.split(args.encode('utf-8'))] + args = [ + arg.decode("utf-8") for arg in shlex.split(args.encode("utf-8")) + ] except Exception as exc: raise Exception("line {}: {}".format(lineno + 1, exc)) from None - yield Command(negated=negated, cmd=cmd, args=args, lineno=lineno+1, context=line) + yield Command( + negated=negated, cmd=cmd, args=args, lineno=lineno + 1, context=line + ) def _flatten(node, acc): @@ -312,22 +338,24 @@ def _flatten(node, acc): def flatten(node): acc = [] _flatten(node, acc) - return ''.join(acc) + return "".join(acc) def make_xml(text): - xml = ET.XML('%s' % text) + xml = ET.XML("%s" % text) return xml def normalize_xpath(path): path = path.replace("{{channel}}", channel) - if path.startswith('//'): - return '.' + path # avoid warnings - elif path.startswith('.//'): + if path.startswith("//"): + return "." + path # avoid warnings + elif path.startswith(".//"): return path else: - raise InvalidCheck('Non-absolute XPath is not supported due to implementation issues') + raise InvalidCheck( + "Non-absolute XPath is not supported due to implementation issues" + ) class CachedFiles(object): @@ -338,12 +366,12 @@ class CachedFiles(object): self.last_path = None def resolve_path(self, path): - if path != '-': + if path != "-": path = os.path.normpath(path) self.last_path = path return path elif self.last_path is None: - raise InvalidCheck('Tried to use the previous path in the first command') + raise InvalidCheck("Tried to use the previous path in the first command") else: return self.last_path @@ -356,10 +384,10 @@ class CachedFiles(object): return self.files[path] abspath = self.get_absolute_path(path) - if not(os.path.exists(abspath) and os.path.isfile(abspath)): - raise FailedCheck('File does not exist {!r}'.format(path)) + if not (os.path.exists(abspath) and os.path.isfile(abspath)): + raise FailedCheck("File does not exist {!r}".format(path)) - with io.open(abspath, encoding='utf-8') as f: + with io.open(abspath, encoding="utf-8") as f: data = f.read() self.files[path] = data return data @@ -370,15 +398,15 @@ class CachedFiles(object): return self.trees[path] abspath = self.get_absolute_path(path) - if not(os.path.exists(abspath) and os.path.isfile(abspath)): - raise FailedCheck('File does not exist {!r}'.format(path)) + if not (os.path.exists(abspath) and os.path.isfile(abspath)): + raise FailedCheck("File does not exist {!r}".format(path)) - with io.open(abspath, encoding='utf-8') as f: + with io.open(abspath, encoding="utf-8") as f: try: tree = ET.fromstringlist(f.readlines(), CustomHTMLParser()) except Exception as e: - raise RuntimeError( # noqa: B904 FIXME: py2 - 'Cannot parse an HTML file {!r}: {}'.format(path, e) + raise RuntimeError( # noqa: B904 FIXME: py2 + "Cannot parse an HTML file {!r}: {}".format(path, e) ) self.trees[path] = tree return self.trees[path] @@ -386,8 +414,8 @@ class CachedFiles(object): def get_dir(self, path): path = self.resolve_path(path) abspath = self.get_absolute_path(path) - if not(os.path.exists(abspath) and os.path.isdir(abspath)): - raise FailedCheck('Directory does not exist {!r}'.format(path)) + if not (os.path.exists(abspath) and os.path.isdir(abspath)): + raise FailedCheck("Directory does not exist {!r}".format(path)) def check_string(data, pat, regexp): @@ -397,8 +425,8 @@ def check_string(data, pat, regexp): elif regexp: return re.search(pat, data, flags=re.UNICODE) is not None else: - data = ' '.join(data.split()) - pat = ' '.join(pat.split()) + data = " ".join(data.split()) + pat = " ".join(pat.split()) return pat in data @@ -444,19 +472,19 @@ def get_tree_count(tree, path): def check_snapshot(snapshot_name, actual_tree, normalize_to_text): - assert rust_test_path.endswith('.rs') - snapshot_path = '{}.{}.{}'.format(rust_test_path[:-3], snapshot_name, 'html') + assert rust_test_path.endswith(".rs") + snapshot_path = "{}.{}.{}".format(rust_test_path[:-3], snapshot_name, "html") try: - with open(snapshot_path, 'r') as snapshot_file: + with open(snapshot_path, "r") as snapshot_file: expected_str = snapshot_file.read().replace("{{channel}}", channel) except FileNotFoundError: if bless: expected_str = None else: - raise FailedCheck('No saved snapshot value') # noqa: B904 FIXME: py2 + raise FailedCheck("No saved snapshot value") # noqa: B904 FIXME: py2 if not normalize_to_text: - actual_str = ET.tostring(actual_tree).decode('utf-8') + actual_str = ET.tostring(actual_tree).decode("utf-8") else: actual_str = flatten(actual_tree) @@ -464,64 +492,66 @@ def check_snapshot(snapshot_name, actual_tree, normalize_to_text): # 1. Is --bless # 2. Are actual and expected tree different # 3. Are actual and expected text different - if not expected_str \ - or (not normalize_to_text and \ - not compare_tree(make_xml(actual_str), make_xml(expected_str), stderr)) \ - or (normalize_to_text and actual_str != expected_str): - + if ( + not expected_str + or ( + not normalize_to_text + and not compare_tree(make_xml(actual_str), make_xml(expected_str), stderr) + ) + or (normalize_to_text and actual_str != expected_str) + ): if bless: - with open(snapshot_path, 'w') as snapshot_file: + with open(snapshot_path, "w") as snapshot_file: actual_str = actual_str.replace(channel, "{{channel}}") snapshot_file.write(actual_str) else: - print('--- expected ---\n') + print("--- expected ---\n") print(expected_str) - print('\n\n--- actual ---\n') + print("\n\n--- actual ---\n") print(actual_str) print() - raise FailedCheck('Actual snapshot value is different than expected') + raise FailedCheck("Actual snapshot value is different than expected") # Adapted from https://github.com/formencode/formencode/blob/3a1ba9de2fdd494dd945510a4568a3afeddb0b2e/formencode/doctest_xml_compare.py#L72-L120 def compare_tree(x1, x2, reporter=None): if x1.tag != x2.tag: if reporter: - reporter('Tags do not match: %s and %s' % (x1.tag, x2.tag)) + reporter("Tags do not match: %s and %s" % (x1.tag, x2.tag)) return False for name, value in x1.attrib.items(): if x2.attrib.get(name) != value: if reporter: - reporter('Attributes do not match: %s=%r, %s=%r' - % (name, value, name, x2.attrib.get(name))) + reporter( + "Attributes do not match: %s=%r, %s=%r" + % (name, value, name, x2.attrib.get(name)) + ) return False for name in x2.attrib: if name not in x1.attrib: if reporter: - reporter('x2 has an attribute x1 is missing: %s' - % name) + reporter("x2 has an attribute x1 is missing: %s" % name) return False if not text_compare(x1.text, x2.text): if reporter: - reporter('text: %r != %r' % (x1.text, x2.text)) + reporter("text: %r != %r" % (x1.text, x2.text)) return False if not text_compare(x1.tail, x2.tail): if reporter: - reporter('tail: %r != %r' % (x1.tail, x2.tail)) + reporter("tail: %r != %r" % (x1.tail, x2.tail)) return False cl1 = list(x1) cl2 = list(x2) if len(cl1) != len(cl2): if reporter: - reporter('children length differs, %i != %i' - % (len(cl1), len(cl2))) + reporter("children length differs, %i != %i" % (len(cl1), len(cl2))) return False i = 0 for c1, c2 in zip(cl1, cl2): i += 1 if not compare_tree(c1, c2, reporter=reporter): if reporter: - reporter('children %i do not match: %s' - % (i, c1.tag)) + reporter("children %i do not match: %s" % (i, c1.tag)) return False return True @@ -529,14 +559,14 @@ def compare_tree(x1, x2, reporter=None): def text_compare(t1, t2): if not t1 and not t2: return True - if t1 == '*' or t2 == '*': + if t1 == "*" or t2 == "*": return True - return (t1 or '').strip() == (t2 or '').strip() + return (t1 or "").strip() == (t2 or "").strip() def stderr(*args): if sys.version_info.major < 3: - file = codecs.getwriter('utf-8')(sys.stderr) + file = codecs.getwriter("utf-8")(sys.stderr) else: file = sys.stderr @@ -556,21 +586,25 @@ def print_err(lineno, context, err, message=None): def get_nb_matching_elements(cache, c, regexp, stop_at_first): tree = cache.get_tree(c.args[0]) - pat, sep, attr = c.args[1].partition('/@') + pat, sep, attr = c.args[1].partition("/@") if sep: # attribute tree = cache.get_tree(c.args[0]) return check_tree_attr(tree, pat, attr, c.args[2], False) else: # normalized text pat = c.args[1] - if pat.endswith('/text()'): + if pat.endswith("/text()"): pat = pat[:-7] - return check_tree_text(cache.get_tree(c.args[0]), pat, c.args[2], regexp, stop_at_first) + return check_tree_text( + cache.get_tree(c.args[0]), pat, c.args[2], regexp, stop_at_first + ) def check_files_in_folder(c, cache, folder, files): files = files.strip() - if not files.startswith('[') or not files.endswith(']'): - raise InvalidCheck("Expected list as second argument of {} (ie '[]')".format(c.cmd)) + if not files.startswith("[") or not files.endswith("]"): + raise InvalidCheck( + "Expected list as second argument of {} (ie '[]')".format(c.cmd) + ) folder = cache.get_absolute_path(folder) @@ -592,12 +626,18 @@ def check_files_in_folder(c, cache, folder, files): error = 0 if len(files_set) != 0: - print_err(c.lineno, c.context, "Entries not found in folder `{}`: `{}`".format( - folder, files_set)) + print_err( + c.lineno, + c.context, + "Entries not found in folder `{}`: `{}`".format(folder, files_set), + ) error += 1 if len(folder_set) != 0: - print_err(c.lineno, c.context, "Extra entries in folder `{}`: `{}`".format( - folder, folder_set)) + print_err( + c.lineno, + c.context, + "Extra entries in folder `{}`: `{}`".format(folder, folder_set), + ) error += 1 return error == 0 @@ -608,11 +648,11 @@ ERR_COUNT = 0 def check_command(c, cache): try: cerr = "" - if c.cmd in ['has', 'hasraw', 'matches', 'matchesraw']: # string test - regexp = c.cmd.startswith('matches') + if c.cmd in ["has", "hasraw", "matches", "matchesraw"]: # string test + regexp = c.cmd.startswith("matches") # has = file existence - if len(c.args) == 1 and not regexp and 'raw' not in c.cmd: + if len(c.args) == 1 and not regexp and "raw" not in c.cmd: try: cache.get_file(c.args[0]) ret = True @@ -620,24 +660,24 @@ def check_command(c, cache): cerr = str(err) ret = False # hasraw/matchesraw = string test - elif len(c.args) == 2 and 'raw' in c.cmd: + elif len(c.args) == 2 and "raw" in c.cmd: cerr = "`PATTERN` did not match" ret = check_string(cache.get_file(c.args[0]), c.args[1], regexp) # has/matches = XML tree test - elif len(c.args) == 3 and 'raw' not in c.cmd: + elif len(c.args) == 3 and "raw" not in c.cmd: cerr = "`XPATH PATTERN` did not match" ret = get_nb_matching_elements(cache, c, regexp, True) != 0 else: - raise InvalidCheck('Invalid number of {} arguments'.format(c.cmd)) + raise InvalidCheck("Invalid number of {} arguments".format(c.cmd)) - elif c.cmd == 'files': # check files in given folder - if len(c.args) != 2: # files + elif c.cmd == "files": # check files in given folder + if len(c.args) != 2: # files raise InvalidCheck("Invalid number of {} arguments".format(c.cmd)) elif c.negated: raise InvalidCheck("{} doesn't support negative check".format(c.cmd)) ret = check_files_in_folder(c, cache, c.args[0], c.args[1]) - elif c.cmd == 'count': # count test + elif c.cmd == "count": # count test if len(c.args) == 3: # count = count test expected = int(c.args[2]) found = get_tree_count(cache.get_tree(c.args[0]), c.args[1]) @@ -649,15 +689,15 @@ def check_command(c, cache): cerr = "Expected {} occurrences but found {}".format(expected, found) ret = found == expected else: - raise InvalidCheck('Invalid number of {} arguments'.format(c.cmd)) + raise InvalidCheck("Invalid number of {} arguments".format(c.cmd)) - elif c.cmd == 'snapshot': # snapshot test + elif c.cmd == "snapshot": # snapshot test if len(c.args) == 3: # snapshot [snapshot_name, html_path, pattern] = c.args tree = cache.get_tree(html_path) xpath = normalize_xpath(pattern) normalize_to_text = False - if xpath.endswith('/text()'): + if xpath.endswith("/text()"): xpath = xpath[:-7] normalize_to_text = True @@ -671,13 +711,15 @@ def check_command(c, cache): cerr = str(err) ret = False elif len(subtrees) == 0: - raise FailedCheck('XPATH did not match') + raise FailedCheck("XPATH did not match") else: - raise FailedCheck('Expected 1 match, but found {}'.format(len(subtrees))) + raise FailedCheck( + "Expected 1 match, but found {}".format(len(subtrees)) + ) else: - raise InvalidCheck('Invalid number of {} arguments'.format(c.cmd)) + raise InvalidCheck("Invalid number of {} arguments".format(c.cmd)) - elif c.cmd == 'has-dir': # has-dir test + elif c.cmd == "has-dir": # has-dir test if len(c.args) == 1: # has-dir = has-dir test try: cache.get_dir(c.args[0]) @@ -686,22 +728,22 @@ def check_command(c, cache): cerr = str(err) ret = False else: - raise InvalidCheck('Invalid number of {} arguments'.format(c.cmd)) + raise InvalidCheck("Invalid number of {} arguments".format(c.cmd)) - elif c.cmd == 'valid-html': - raise InvalidCheck('Unimplemented valid-html') + elif c.cmd == "valid-html": + raise InvalidCheck("Unimplemented valid-html") - elif c.cmd == 'valid-links': - raise InvalidCheck('Unimplemented valid-links') + elif c.cmd == "valid-links": + raise InvalidCheck("Unimplemented valid-links") else: - raise InvalidCheck('Unrecognized {}'.format(c.cmd)) + raise InvalidCheck("Unrecognized {}".format(c.cmd)) if ret == c.negated: raise FailedCheck(cerr) except FailedCheck as err: - message = '{}{} check failed'.format('!' if c.negated else '', c.cmd) + message = "{}{} check failed".format("!" if c.negated else "", c.cmd) print_err(c.lineno, c.context, str(err), message) except InvalidCheck as err: print_err(c.lineno, c.context, str(err)) @@ -713,18 +755,18 @@ def check(target, commands): check_command(c, cache) -if __name__ == '__main__': +if __name__ == "__main__": if len(sys.argv) not in [3, 4]: - stderr('Usage: {}