From 669cbdce4e40e3d06b168323b97c003d75483ca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Sun, 25 Feb 2024 22:55:35 +0000 Subject: [PATCH 01/13] [MozillaCACerts_jll] Update to v2023-12-12 (#53466) Memo to self: * update the version in `stdlib/MozillaCACerts_jll/Project.toml` * update `MOZILLA_CACERT_VERSION` in `deps/libgit2.version` * generate new checksums with `make -f contrib/refresh_checksums.mk mozillacert` * manually delete old checksums in `deps/checksums/cacert-` --- deps/checksums/cacert-2023-01-10.pem/md5 | 1 - deps/checksums/cacert-2023-01-10.pem/sha512 | 1 - deps/checksums/cacert-2023-12-12.pem/md5 | 1 + deps/checksums/cacert-2023-12-12.pem/sha512 | 1 + deps/libgit2.version | 3 ++- stdlib/MozillaCACerts_jll/Project.toml | 3 ++- 6 files changed, 6 insertions(+), 4 deletions(-) delete mode 100644 deps/checksums/cacert-2023-01-10.pem/md5 delete mode 100644 deps/checksums/cacert-2023-01-10.pem/sha512 create mode 100644 deps/checksums/cacert-2023-12-12.pem/md5 create mode 100644 deps/checksums/cacert-2023-12-12.pem/sha512 diff --git a/deps/checksums/cacert-2023-01-10.pem/md5 b/deps/checksums/cacert-2023-01-10.pem/md5 deleted file mode 100644 index 92063050b50f3..0000000000000 --- a/deps/checksums/cacert-2023-01-10.pem/md5 +++ /dev/null @@ -1 +0,0 @@ -e7cf471ba7c88f4e313f492a76e624b3 diff --git a/deps/checksums/cacert-2023-01-10.pem/sha512 b/deps/checksums/cacert-2023-01-10.pem/sha512 deleted file mode 100644 index d3322e5890f81..0000000000000 --- a/deps/checksums/cacert-2023-01-10.pem/sha512 +++ /dev/null @@ -1 +0,0 @@ -08cd35277bf2260cb3232d7a7ca3cce6b2bd58af9221922d2c6e9838a19c2f96d1ca6d77f3cc2a3ab611692f9fec939e9b21f67442282e867a487b0203ee0279 diff --git a/deps/checksums/cacert-2023-12-12.pem/md5 b/deps/checksums/cacert-2023-12-12.pem/md5 new file mode 100644 index 0000000000000..fa4b90b0b2ddd --- /dev/null +++ b/deps/checksums/cacert-2023-12-12.pem/md5 @@ -0,0 +1 @@ +1e305b4e910d204ab7b4c18ec0cf0f27 diff --git a/deps/checksums/cacert-2023-12-12.pem/sha512 b/deps/checksums/cacert-2023-12-12.pem/sha512 new file mode 100644 index 0000000000000..8ce26f24dffd9 --- /dev/null +++ b/deps/checksums/cacert-2023-12-12.pem/sha512 @@ -0,0 +1 @@ +dcbfe08d39efdd8de555b31e1050757900d08448c61f8a67c055f14514e5d47e734f6874b5ae628021c35ebc8dabdfdac5808df0b3a073d4f9246cca4b725fe8 diff --git a/deps/libgit2.version b/deps/libgit2.version index 9bd56f1bd0001..064c95094adb3 100644 --- a/deps/libgit2.version +++ b/deps/libgit2.version @@ -10,4 +10,5 @@ LIBGIT2_SHA1=a2bde63741977ca0f4ef7db2f609df320be67a08 # Specify the version of the Mozilla CA Certificate Store to obtain. # The versions of cacert.pem are identified by the date (YYYY-MM-DD) of their changes. # See https://curl.haxx.se/docs/caextract.html for more details. -MOZILLA_CACERT_VERSION := 2023-01-10 +# Keep in sync with `stdlib/MozillaCACerts_jll/Project.toml`. +MOZILLA_CACERT_VERSION := 2023-12-12 diff --git a/stdlib/MozillaCACerts_jll/Project.toml b/stdlib/MozillaCACerts_jll/Project.toml index cef860fda4acd..b4f667b974736 100644 --- a/stdlib/MozillaCACerts_jll/Project.toml +++ b/stdlib/MozillaCACerts_jll/Project.toml @@ -1,6 +1,7 @@ name = "MozillaCACerts_jll" uuid = "14a3606d-f60d-562e-9121-12d972cd8159" -version = "2023.01.10" +# Keep in sync with `deps/libgit2.version`. +version = "2023.12.12" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" From 90d03b2bbec84488af7792258bf99fa2606b77a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Mon, 26 Feb 2024 00:37:13 +0000 Subject: [PATCH 02/13] [LibGit2_jll] Update to v1.7.2 (#53467) Memo to self: * update version number in `stdlib/LibGit2_jll/Project.toml` * update test result in `stdlib/LibGit2_jll/test/runtests.jl` * update version number and commit sha in `deps/libgit2.version` * refresh checksums with `make -f contrib/refresh_checksums.mk -j libgit2` --- deps/checksums/libgit2 | 68 ++++++++++++++--------------- deps/libgit2.version | 4 +- stdlib/LibGit2_jll/Project.toml | 2 +- stdlib/LibGit2_jll/test/runtests.jl | 2 +- 4 files changed, 38 insertions(+), 38 deletions(-) diff --git a/deps/checksums/libgit2 b/deps/checksums/libgit2 index 63d67671b12a4..78b82572f3898 100644 --- a/deps/checksums/libgit2 +++ b/deps/checksums/libgit2 @@ -1,34 +1,34 @@ -LibGit2.v1.7.1+0.aarch64-apple-darwin.tar.gz/md5/80102fd8cd633a4875a1257bd61d4e17 -LibGit2.v1.7.1+0.aarch64-apple-darwin.tar.gz/sha512/3cc3679923c36e0020e692e79112a8fa71b53c1b83c9bea8d6defda124722a67c2859089d36fddef7be4547539575483db32de8137b43f7fc97843e579a02696 -LibGit2.v1.7.1+0.aarch64-linux-gnu.tar.gz/md5/74be95a3f7886a9804964f024df5311f -LibGit2.v1.7.1+0.aarch64-linux-gnu.tar.gz/sha512/3ad8a3c9ced9be2ab5fefe651f445a26900beae743127dcd1f887d01a7672d5d6c523641ba7d402620f3c44a1cc9557e43e11ad1692726c8cfabecca59a030e9 -LibGit2.v1.7.1+0.aarch64-linux-musl.tar.gz/md5/e63f4351250b4f4ac60d66b0bed2ddf5 -LibGit2.v1.7.1+0.aarch64-linux-musl.tar.gz/sha512/8f2dd17fe55b7cf7cf60504e5b630b22ce27e4e89d75f7e93dba3b112f662470612987e09abd82c2e3df48fc3c0fe1dbf98c690d972edb50c10a5571741cd9e8 -LibGit2.v1.7.1+0.armv6l-linux-gnueabihf.tar.gz/md5/f06611068a36fa575ec8eb219c068723 -LibGit2.v1.7.1+0.armv6l-linux-gnueabihf.tar.gz/sha512/04c554b9617300cea7750d18590e1a5629e70274ef1e1e8fdabbb4347e46fd8a68e82ba21714d7cd3809c3b6de2e254baca35ff60a4be87485643c460b10ac73 -LibGit2.v1.7.1+0.armv6l-linux-musleabihf.tar.gz/md5/7135ca6e52bf63855c5b6aa45d59ad80 -LibGit2.v1.7.1+0.armv6l-linux-musleabihf.tar.gz/sha512/e542180d2d8a0896ec586edac03b91d48d2ece3d22220d09b6e717b1b95a38bc1de2ae0faeed39dd3e99150684441bfb0504b55b3e18e543e00561f91147d405 -LibGit2.v1.7.1+0.armv7l-linux-gnueabihf.tar.gz/md5/7ffc92c821ec99bd76865ece43f5face -LibGit2.v1.7.1+0.armv7l-linux-gnueabihf.tar.gz/sha512/c945a0895be07479fd94c3c127060e58866bc9b9c93e80dc923ecdda6689e43d566896ecf4bfc7d85ca710b9ee51e6d85dec423edc48a3a2066db0fbb118d073 -LibGit2.v1.7.1+0.armv7l-linux-musleabihf.tar.gz/md5/3d00a6223612c23ac6b3c1f44bff8119 -LibGit2.v1.7.1+0.armv7l-linux-musleabihf.tar.gz/sha512/c3ef7783f140b28ad2d10e1c16f5be683d3332a4f9db5d26fdf3f2ac2b750aa0ceaec928740a9bdf7f4d9e83f666aa6e5fdd9c019630bf46f6797000943e1510 -LibGit2.v1.7.1+0.i686-linux-gnu.tar.gz/md5/6ea4e6777f5a8630f9fa98fb6a4a4ac7 -LibGit2.v1.7.1+0.i686-linux-gnu.tar.gz/sha512/d62a46b54dfc491a88fa35d06f3ed9c76ce676473b33acd5382e72ce07e6a313505755476c4732b7a22cd774ddcdf4ea5e8a5b62b93eb48b67363911655ac177 -LibGit2.v1.7.1+0.i686-linux-musl.tar.gz/md5/9f74dc4e93886f011412a4f61dfb487f -LibGit2.v1.7.1+0.i686-linux-musl.tar.gz/sha512/1370cab2ef917aa759dd4986f247a6b4878f12c4b17399fa75c9a2878f86c136e6f2f998a396df0757bf36ac09d5d194e4b7688705d115f09c176f4a5ab22347 -LibGit2.v1.7.1+0.i686-w64-mingw32.tar.gz/md5/ce866e600b2ad8c0fd54ff8c57dc015c -LibGit2.v1.7.1+0.i686-w64-mingw32.tar.gz/sha512/c7848b39f3515452e13fb156ee645f9a8d3917374ba874b10437b417b3c8e9a108e014b3baf30c7ced5fd0034d4f37de7e7d76fb105358d8e953dca30c873dc6 -LibGit2.v1.7.1+0.powerpc64le-linux-gnu.tar.gz/md5/b7c2f120e33f499860cb1e096923e7fe -LibGit2.v1.7.1+0.powerpc64le-linux-gnu.tar.gz/sha512/3df8e54d2086fbedb55b5dc31a2010f2ecd277089293473607e780340882bda5b2f9a2cc1c53c88bd7fcca0791cc2530645ceda17de3f37bb1ff98a19ccb85cf -LibGit2.v1.7.1+0.x86_64-apple-darwin.tar.gz/md5/b5334bd7e44c2c28705bb816fe03b9b7 -LibGit2.v1.7.1+0.x86_64-apple-darwin.tar.gz/sha512/d91cfde393499687cc699d55184c58ee5f543108902bf1f08fde2270dec0f38e0d70cbc7af04ffe46952afad12ce008e745f4aae9084f23df58982c14b48117c -LibGit2.v1.7.1+0.x86_64-linux-gnu.tar.gz/md5/9e2e2fe324a40bb0a5364d218c5ce45e -LibGit2.v1.7.1+0.x86_64-linux-gnu.tar.gz/sha512/da7e28c20c09c5c0731fd5cdff6fa6c319b2c4757d5c4228fc287238cd649f98c689814480119f21cbb938a29f52c895021b44c74eccc2f93ae51766555d9b6a -LibGit2.v1.7.1+0.x86_64-linux-musl.tar.gz/md5/7147480b9520116eb63ee3c30fa60a21 -LibGit2.v1.7.1+0.x86_64-linux-musl.tar.gz/sha512/f3dfb2a416cb786f229fe9eb3ef653a30ba5ebf3b978475f0a10fa79fa68b7bce9b6d99aed19f8dfb5599d988e3c6d4ede9ef1a6ccdbb3c2ea61f76b97d7fb29 -LibGit2.v1.7.1+0.x86_64-unknown-freebsd.tar.gz/md5/39e1a6d463e52ca0b2a1a8e6c3c4a286 -LibGit2.v1.7.1+0.x86_64-unknown-freebsd.tar.gz/sha512/3978ba9923cc8a188aca36d7320d46b2788de27142d11920976c47ad43574ad7056539812cebab62550e656b263c2d277754c341bd83d013de608a91e6a0aad3 -LibGit2.v1.7.1+0.x86_64-w64-mingw32.tar.gz/md5/7d92c546023f460741a8187999b76bbe -LibGit2.v1.7.1+0.x86_64-w64-mingw32.tar.gz/sha512/da00d54f969ce3b70cc95dda281ddfafee72073164c31d7999053ed704a59401d64894ad702306d6e19eb1a60e5e98e5960c9c7e9a0e1645a0f3048422e62eb9 -libgit2-e6325351ceee58cf56f58bdce61b38907805544f.tar.gz/md5/08777cc257825f218ceac1a24abafdc9 -libgit2-e6325351ceee58cf56f58bdce61b38907805544f.tar.gz/sha512/ebeaf3bb12ce7d58cd6d36e0123168de3af8f083f707dc20df9781537e38188a176667ac51daf8d9006d54f2beed13fbfff6c26fbb48e3228988578ef8fbc9b7 +LibGit2.v1.7.2+0.aarch64-apple-darwin.tar.gz/md5/069fa8cbd69e98a6196bd24bb427ff47 +LibGit2.v1.7.2+0.aarch64-apple-darwin.tar.gz/sha512/bacaf03e8aa28a55af2ae031f09a22f0a9cecb20257ee9778f37d87eb4ed21ff25dbb33ac342b134edc2a9584c0c57e6eabf7dbe78b031e9e45c2448bd8a317c +LibGit2.v1.7.2+0.aarch64-linux-gnu.tar.gz/md5/3bc5dfb163045c335aec05097702ddd4 +LibGit2.v1.7.2+0.aarch64-linux-gnu.tar.gz/sha512/c8055e51713f6fe6f064c7e4626db7a70d07af6e5c8cb031e88ef8ea728accdb92a449f738fb248c0afbc9698d30d0670fa5cf640df564886887c7ce4dbc7124 +LibGit2.v1.7.2+0.aarch64-linux-musl.tar.gz/md5/23440824a3ec0a0d82fa8adccac63534 +LibGit2.v1.7.2+0.aarch64-linux-musl.tar.gz/sha512/040874d092d7a11c5bfa284e95b86335792ffa6b868e8c7165ca304647d82ffbc7a72b65bb92038abd1bfa545e831d5b2a658b3f5891377735f85d3e4ddff7b2 +LibGit2.v1.7.2+0.armv6l-linux-gnueabihf.tar.gz/md5/3ffc0954875a20f610f6852c522311f2 +LibGit2.v1.7.2+0.armv6l-linux-gnueabihf.tar.gz/sha512/35767e10a36a0025539a354ef5be2ec4031457c0c1121a07f4616c774e48bb85425732935a12718d23627b4bdf1fb5c7fe6b220cb4e2bcb94b9d26c743af0004 +LibGit2.v1.7.2+0.armv6l-linux-musleabihf.tar.gz/md5/73acea595fc31967d7fe1e808f4cc47c +LibGit2.v1.7.2+0.armv6l-linux-musleabihf.tar.gz/sha512/e124681a7b7b1ff64a1ca073ee6fcc75fc2b11ab0a3404b0a2bc9944854c4048e576697254cd8efed1d6c7103ac2e1bd574a75c6c3d8a383775d48170ef6d474 +LibGit2.v1.7.2+0.armv7l-linux-gnueabihf.tar.gz/md5/b710035b0be0c7e4810b9282912369a0 +LibGit2.v1.7.2+0.armv7l-linux-gnueabihf.tar.gz/sha512/e34b2956a869303a5b6bed059f326989e4e95f039fa3d1b75fc6f80c6d1170df96e2ea809df05aad59685751eb4666a0a05e0c3b456bcace2b0570b174b2b541 +LibGit2.v1.7.2+0.armv7l-linux-musleabihf.tar.gz/md5/aa4c7374dda73266cd387596fa31c258 +LibGit2.v1.7.2+0.armv7l-linux-musleabihf.tar.gz/sha512/54f6c9bd7dd1ee0438b817b1b18a94ce6f18838613524f146cf37f7d01319dd7c05d19d352376454ed2658e9dd839fede32db05748d9c352b56c3f0fe01edebc +LibGit2.v1.7.2+0.i686-linux-gnu.tar.gz/md5/2cf407e8cf5f7c7c984b48704935afaa +LibGit2.v1.7.2+0.i686-linux-gnu.tar.gz/sha512/44224ccf773b9f77979c1130cbb893d80c934918940ab9357bff7d92b97bdf1671d4263d121a603a6c12e60375bafc38b4bcac9a12cb0abb4665b5848d12946a +LibGit2.v1.7.2+0.i686-linux-musl.tar.gz/md5/742b947992f9f003a49c480165df1c87 +LibGit2.v1.7.2+0.i686-linux-musl.tar.gz/sha512/4d1a0c5c119f391be76d93ee7e82c6e38c8cda5c172c3d431bed6c6923776d4ad194c88509203332bed23f4c42581255a319a2ca45b6433b3fb68b3dc0aa1f02 +LibGit2.v1.7.2+0.i686-w64-mingw32.tar.gz/md5/476c290758970376ddfdcad25ba74c7c +LibGit2.v1.7.2+0.i686-w64-mingw32.tar.gz/sha512/dc76e0563b45aead1187fd7abfe411e3fbc21ff45983b693c11db4265d39fc3f51d167fe447f6a7efb1f3ec1e35a9d0edb1c3444ed50be62770dfea545fbddae +LibGit2.v1.7.2+0.powerpc64le-linux-gnu.tar.gz/md5/3ce536ea1ad7facca14c19c84106e8e5 +LibGit2.v1.7.2+0.powerpc64le-linux-gnu.tar.gz/sha512/d52d400249c7ed16084b13fde81f784cbf3b13b7081944872986b216b7faf186b7c8ff28626504d461c6059c7b4962acde0b15dc2e36007492210568a0f425f7 +LibGit2.v1.7.2+0.x86_64-apple-darwin.tar.gz/md5/c59af177b7ebdcfd52312a40d7832ee8 +LibGit2.v1.7.2+0.x86_64-apple-darwin.tar.gz/sha512/5bae0efc71421f28e4a3b2aca70ef1810b5810ed3df3d3577b8a7e956ea895f4b9efdabf17a32130e1f71fede4ceae7246d099b71147686e5722abdf56d50778 +LibGit2.v1.7.2+0.x86_64-linux-gnu.tar.gz/md5/1a55eb14294730b0ba7a23df3aac27ee +LibGit2.v1.7.2+0.x86_64-linux-gnu.tar.gz/sha512/21f7aea927bed22da1b974eab4d6f3413cc41e47b5a5e5bbfff6690474d6f374952b81549345a68c9227d1f3ef9e76578c81776cd1c41e75330c9f2dd1437c7b +LibGit2.v1.7.2+0.x86_64-linux-musl.tar.gz/md5/33a9bfb5a805ca6ca695196c2e94183e +LibGit2.v1.7.2+0.x86_64-linux-musl.tar.gz/sha512/924c2c2cd9baad369b21c17364164dbff7ecda153cb1ed89a4a7539407f3bdc54e87304ed2b7e26ba8046077cb0b3645e9263d53eb4b220436a2e150a77109c3 +LibGit2.v1.7.2+0.x86_64-unknown-freebsd.tar.gz/md5/8d27555b9a1bc086c4c3056cda876bd2 +LibGit2.v1.7.2+0.x86_64-unknown-freebsd.tar.gz/sha512/8ca7a589a328908ee10490230c963ae1292f9cb7c2c427c26ca5d6e4985d56ef76d02f98e05e4fc655cc5e92e2e405d63896a180bc33ebd4b852d2ff355c0339 +LibGit2.v1.7.2+0.x86_64-w64-mingw32.tar.gz/md5/3d7ac5a2af376a2ba0b335cb84710874 +LibGit2.v1.7.2+0.x86_64-w64-mingw32.tar.gz/sha512/5bdbb1110fa7c5bfaac0ba63002f9b1f480abab1cf3e284146352c30027381c23919745a0c490e202e8d856503f5c2bb2390a6bc32af533def7d31f8d6f7be31 +libgit2-a418d9d4ab87bae16b87d8f37143a4687ae0e4b2.tar.gz/md5/c67e5a2358f01d26b78269639ba20148 +libgit2-a418d9d4ab87bae16b87d8f37143a4687ae0e4b2.tar.gz/sha512/c82dc18bacb45f82c72f09e5525fd47191c8673a553df9faa05290c33dfdadfff9784341e68790130a14b12267c795f4ca166481fdf9674d2b70e8228bbeb11d diff --git a/deps/libgit2.version b/deps/libgit2.version index 064c95094adb3..65f3e7670e4af 100644 --- a/deps/libgit2.version +++ b/deps/libgit2.version @@ -3,8 +3,8 @@ LIBGIT2_JLL_NAME := LibGit2 ## source build -LIBGIT2_BRANCH=v1.7.1 -LIBGIT2_SHA1=a2bde63741977ca0f4ef7db2f609df320be67a08 +LIBGIT2_BRANCH=v1.7.2 +LIBGIT2_SHA1=a418d9d4ab87bae16b87d8f37143a4687ae0e4b2 ## Other deps # Specify the version of the Mozilla CA Certificate Store to obtain. diff --git a/stdlib/LibGit2_jll/Project.toml b/stdlib/LibGit2_jll/Project.toml index e64d86dc6c9b7..1e13d0228488f 100644 --- a/stdlib/LibGit2_jll/Project.toml +++ b/stdlib/LibGit2_jll/Project.toml @@ -1,6 +1,6 @@ name = "LibGit2_jll" uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" -version = "1.7.1+0" +version = "1.7.2+0" [deps] MbedTLS_jll = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" diff --git a/stdlib/LibGit2_jll/test/runtests.jl b/stdlib/LibGit2_jll/test/runtests.jl index 86dcf659e7ab2..6d83f6e447453 100644 --- a/stdlib/LibGit2_jll/test/runtests.jl +++ b/stdlib/LibGit2_jll/test/runtests.jl @@ -7,5 +7,5 @@ using Test, Libdl, LibGit2_jll minor = Ref{Cint}(0) patch = Ref{Cint}(0) @test ccall((:git_libgit2_version, libgit2), Cint, (Ref{Cint}, Ref{Cint}, Ref{Cint}), major, minor, patch) == 0 - @test VersionNumber(major[], minor[], patch[]) == v"1.7.1" + @test VersionNumber(major[], minor[], patch[]) == v"1.7.2" end From 849d551d27950f3c7e7a314773e9261a9d83ffea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Mon, 9 May 2022 00:48:39 +0100 Subject: [PATCH 03/13] Use `@test ... broken=...` instead of `@test_broken` --- stdlib/LinearAlgebra/test/triangular.jl | 18 ++++-------------- stdlib/TOML/test/toml_test.jl | 12 ++---------- test/compiler/inference.jl | 6 +----- test/stacktraces.jl | 12 +++--------- 4 files changed, 10 insertions(+), 38 deletions(-) diff --git a/stdlib/LinearAlgebra/test/triangular.jl b/stdlib/LinearAlgebra/test/triangular.jl index 97bf756044c66..7b222234c5fcb 100644 --- a/stdlib/LinearAlgebra/test/triangular.jl +++ b/stdlib/LinearAlgebra/test/triangular.jl @@ -1013,13 +1013,8 @@ end @test 2\L == 2\B @test real(L) == real(B) @test imag(L) == imag(B) - if A isa Matrix - @test transpose!(MT(copy(A))) == transpose(L) - @test adjoint!(MT(copy(A))) == adjoint(L) - else - @test_broken transpose!(MT(copy(A))) == transpose(L) - @test_broken adjoint!(MT(copy(A))) == adjoint(L) - end + @test transpose!(MT(copy(A))) == transpose(L) broken=!(A isa Matrix) + @test adjoint!(MT(copy(A))) == adjoint(L) broken=!(A isa Matrix) end end @@ -1039,13 +1034,8 @@ end @test 2\U == 2\B @test real(U) == real(B) @test imag(U) == imag(B) - if A isa Matrix - @test transpose!(MT(copy(A))) == transpose(U) - @test adjoint!(MT(copy(A))) == adjoint(U) - else - @test_broken transpose!(MT(copy(A))) == transpose(U) - @test_broken adjoint!(MT(copy(A))) == adjoint(U) - end + @test transpose!(MT(copy(A))) == transpose(U) broken=!(A isa Matrix) + @test adjoint!(MT(copy(A))) == adjoint(U) broken=!(A isa Matrix) end end end diff --git a/stdlib/TOML/test/toml_test.jl b/stdlib/TOML/test/toml_test.jl index c22c01acf1870..cdd8950677c75 100644 --- a/stdlib/TOML/test/toml_test.jl +++ b/stdlib/TOML/test/toml_test.jl @@ -72,11 +72,7 @@ for (root, dirs, files) in walkdir(valid_test_folder) rel = replace(rel, '\\' => '/') end v = check_valid(splitext(file)[1]) - if rel in failures - @test_broken v - else - @test v - end + @test v broken=rel in failures end end end @@ -145,11 +141,7 @@ for (root, dirs, files) in walkdir(invalid_test_folder) rel = replace(rel, '\\' => '/') end v = check_invalid(file) - if rel in failures - @test_broken v - else - @test v - end + @test v broken=rel in failures end end end diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index d6d65faaaf7bb..a9b1d89d40e9d 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -184,11 +184,7 @@ Base.ndims(g::e43296) = ndims(typeof(g)) # PR 22120 function tuplemerge_test(a, b, r, commutative=true) @test r == Core.Compiler.tuplemerge(a, b) - if commutative - @test r == Core.Compiler.tuplemerge(b, a) - else - @test_broken r == Core.Compiler.tuplemerge(b, a) - end + @test r == Core.Compiler.tuplemerge(b, a) broken=!commutative end tuplemerge_test(Tuple{Int}, Tuple{String}, Tuple{Union{Int, String}}) tuplemerge_test(Tuple{Int}, Tuple{String, String}, Tuple) diff --git a/test/stacktraces.jl b/test/stacktraces.jl index caea8158315ff..69b3b71d03167 100644 --- a/test/stacktraces.jl +++ b/test/stacktraces.jl @@ -92,15 +92,9 @@ can_inline = Bool(Base.JLOptions().can_inline) for (frame, func, inlined) in zip(trace, [g,h,f], (can_inline, can_inline, false)) @test frame.func === typeof(func).name.mt.name # broken until #50082 can be addressed - if inlined - @test frame.linfo.def.module === which(func, (Any,)).module broken=true - @test frame.linfo.def === which(func, (Any,)) broken=true - @test frame.linfo.specTypes === Tuple{typeof(func), Int} broken=true - else - @test frame.linfo.def.module === which(func, (Any,)).module - @test frame.linfo.def === which(func, (Any,)) - @test frame.linfo.specTypes === Tuple{typeof(func), Int} - end + @test frame.linfo.def.module === which(func, (Any,)).module broken=inlined + @test frame.linfo.def === which(func, (Any,)) broken=inlined + @test frame.linfo.specTypes === Tuple{typeof(func), Int} broken=inlined # line @test frame.file === Symbol(@__FILE__) @test !frame.from_c From 34a515189a653080776e9d24295a0cfee393fe90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Mon, 26 Feb 2024 01:49:17 +0000 Subject: [PATCH 04/13] Use `@test ... skip=...` instead of `@test_skip` --- test/file.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/file.jl b/test/file.jl index c32f655eb677e..e0241c5ef38df 100644 --- a/test/file.jl +++ b/test/file.jl @@ -1677,19 +1677,19 @@ end chmod(fpath, 0o644) @test !Sys.isexecutable(fpath) @test Sys.isreadable(fpath) - Sys.iswindows() ? @test_skip(Sys.iswriteable(fpath)) : @test(Sys.iswriteable(fpath)) + @test Sys.iswriteable(fpath) skip=Sys.iswindows() chmod(fpath, 0o755) @test Sys.isexecutable(fpath) @test Sys.isreadable(fpath) - Sys.iswindows() ? @test_skip(Sys.iswriteable(fpath)) : @test(Sys.iswriteable(fpath)) + @test Sys.iswriteable(fpath) skip=Sys.iswindows() chmod(fpath, 0o444) @test !Sys.isexecutable(fpath) @test Sys.isreadable(fpath) @test !Sys.iswriteable(fpath) chmod(fpath, 0o244) @test !Sys.isexecutable(fpath) - Sys.iswindows() ? @test_skip(!Sys.isreadable(fpath)) : @test(!Sys.isreadable(fpath)) - Sys.iswindows() ? @test_skip(Sys.iswriteable(fpath)) : @test(Sys.iswriteable(fpath)) + @test !Sys.isreadable(fpath) skip=Sys.iswindows() + @test Sys.iswriteable(fpath) skip=Sys.iswindows() # Ensure that, on Windows, where inheritance is default, # chmod still behaves as we expect. From 4b47cc48302281a705abf550748408eb78ec39d3 Mon Sep 17 00:00:00 2001 From: Eric Hanson <5846501+ericphanson@users.noreply.github.com> Date: Mon, 26 Feb 2024 08:36:47 +0100 Subject: [PATCH 05/13] Remove stale explicit imports from many stdlibs (#53464) Found via my new https://github.com/ericphanson/ExplicitImports.jl ```julia using ExplicitImports ExplicitImports.inspect_session(; inner=print_stale_explicit_imports) ``` These are not being used in the modules they are being imported into (or in some cases they are being used, but only in a qualified way where the explicit import is unnecessary). It can happen that someone imports a name into a module in order to have it available in that namespace, to then access it from another module (e.g. `TOML.Internals` seems to work like this). I've tried to notice those situations and not remove the imports in cases where I suspect the import is playing such a role, but hopefully CI will figure out if I got it right in all cases. I only looked at stdlibs that happened to be loaded in my Julia session and whose code is in this repo, so there are probably more stale explicit imports out there. --- stdlib/Dates/src/Dates.jl | 2 +- stdlib/FileWatching/src/pidfile.jl | 2 -- stdlib/InteractiveUtils/src/InteractiveUtils.jl | 2 +- stdlib/LibGit2/Project.toml | 1 - stdlib/LibGit2/src/LibGit2.jl | 3 +-- stdlib/LibGit2/src/consts.jl | 2 +- stdlib/LinearAlgebra/src/LinearAlgebra.jl | 2 +- stdlib/LinearAlgebra/src/blas.jl | 3 +-- stdlib/LinearAlgebra/src/structuredbroadcast.jl | 2 +- stdlib/REPL/src/LineEdit.jl | 3 +-- stdlib/REPL/src/REPL.jl | 2 -- stdlib/REPL/src/REPLCompletions.jl | 2 +- stdlib/REPL/src/Terminals.jl | 4 +--- stdlib/Serialization/src/Serialization.jl | 2 +- stdlib/Sockets/src/Sockets.jl | 2 +- 15 files changed, 12 insertions(+), 22 deletions(-) diff --git a/stdlib/Dates/src/Dates.jl b/stdlib/Dates/src/Dates.jl index bbfcdbee3f3d1..a4600a5f82043 100644 --- a/stdlib/Dates/src/Dates.jl +++ b/stdlib/Dates/src/Dates.jl @@ -32,7 +32,7 @@ for more information. """ module Dates -import Base: ==, isless, div, fld, mod, rem, gcd, lcm, +, -, *, /, %, broadcast +import Base: ==, isless, div, fld, mod, rem, gcd, lcm, +, -, *, /, % using Printf: @sprintf using Base.Iterators diff --git a/stdlib/FileWatching/src/pidfile.jl b/stdlib/FileWatching/src/pidfile.jl index 71b596ba35f12..0ee86e70f8465 100644 --- a/stdlib/FileWatching/src/pidfile.jl +++ b/stdlib/FileWatching/src/pidfile.jl @@ -7,8 +7,6 @@ using Base: IOError, UV_EEXIST, UV_ESRCH, Process -using Base.Libc: rand - using Base.Filesystem: File, open, JL_O_CREAT, JL_O_RDWR, JL_O_RDONLY, JL_O_EXCL, rename, samefile, path_separator diff --git a/stdlib/InteractiveUtils/src/InteractiveUtils.jl b/stdlib/InteractiveUtils/src/InteractiveUtils.jl index 519acfc8a2f33..a0020090e451d 100644 --- a/stdlib/InteractiveUtils/src/InteractiveUtils.jl +++ b/stdlib/InteractiveUtils/src/InteractiveUtils.jl @@ -15,7 +15,7 @@ export apropos, edit, less, code_warntype, code_llvm, code_native, methodswith, import Base.Docs.apropos -using Base: unwrap_unionall, rewrap_unionall, isdeprecated, Bottom, show_unquoted, summarysize, +using Base: unwrap_unionall, rewrap_unionall, isdeprecated, Bottom, summarysize, signature_type, format_bytes using Base.Libc using Markdown diff --git a/stdlib/LibGit2/Project.toml b/stdlib/LibGit2/Project.toml index 83d359d6a4f1a..8432a32cd240b 100644 --- a/stdlib/LibGit2/Project.toml +++ b/stdlib/LibGit2/Project.toml @@ -3,7 +3,6 @@ uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" version = "1.11.0" [deps] -Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" LibGit2_jll = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" NetworkOptions = "ca575930-c2e3-43a9-ace4-1e988b2c1908" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" diff --git a/stdlib/LibGit2/src/LibGit2.jl b/stdlib/LibGit2/src/LibGit2.jl index 43b960e8d509d..04435dd577c19 100644 --- a/stdlib/LibGit2/src/LibGit2.jl +++ b/stdlib/LibGit2/src/LibGit2.jl @@ -6,8 +6,7 @@ Interface to [libgit2](https://libgit2.org/). module LibGit2 import Base: == -using Base: something, notnothing -using Base64: base64decode +using Base: something using NetworkOptions using Printf: @printf using SHA: sha1, sha256 diff --git a/stdlib/LibGit2/src/consts.jl b/stdlib/LibGit2/src/consts.jl index 1f28a3bdbe887..5a5b8b74e7127 100644 --- a/stdlib/LibGit2/src/consts.jl +++ b/stdlib/LibGit2/src/consts.jl @@ -2,7 +2,7 @@ module Consts -import ..LibGit2: version, ensure_initialized +import ..LibGit2: version const HEAD_FILE = "HEAD" const FETCH_HEAD = "FETCH_HEAD" diff --git a/stdlib/LinearAlgebra/src/LinearAlgebra.jl b/stdlib/LinearAlgebra/src/LinearAlgebra.jl index acacf4b20cfc7..9b9aaf0d9581d 100644 --- a/stdlib/LinearAlgebra/src/LinearAlgebra.jl +++ b/stdlib/LinearAlgebra/src/LinearAlgebra.jl @@ -16,7 +16,7 @@ import Base: USE_BLAS64, abs, acos, acosh, acot, acoth, acsc, acsch, adjoint, as permutedims, permuterows!, power_by_squaring, promote_rule, real, sec, sech, setindex!, show, similar, sin, sincos, sinh, size, sqrt, strides, stride, tan, tanh, transpose, trunc, typed_hcat, vec, view, zero -using Base: IndexLinear, promote_eltype, promote_op, promote_typeof, print_matrix, +using Base: IndexLinear, promote_eltype, promote_op, print_matrix, @propagate_inbounds, reduce, typed_hvcat, typed_vcat, require_one_based_indexing, splat using Base.Broadcast: Broadcasted, broadcasted diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 5d8821cd6e009..7bf7f8bf95100 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -5,7 +5,6 @@ Interface to BLAS subroutines. """ module BLAS -import Base: copyto! using Base: require_one_based_indexing, USE_BLAS64 export @@ -85,7 +84,7 @@ export trsm!, trsm -using ..LinearAlgebra: libblastrampoline, BlasReal, BlasComplex, BlasFloat, BlasInt, DimensionMismatch, checksquare, stride1, chkstride1 +using ..LinearAlgebra: libblastrampoline, BlasReal, BlasComplex, BlasFloat, BlasInt, DimensionMismatch, checksquare, chkstride1 include("lbt.jl") diff --git a/stdlib/LinearAlgebra/src/structuredbroadcast.jl b/stdlib/LinearAlgebra/src/structuredbroadcast.jl index a227b678c9934..e5393bfc719f1 100644 --- a/stdlib/LinearAlgebra/src/structuredbroadcast.jl +++ b/stdlib/LinearAlgebra/src/structuredbroadcast.jl @@ -2,7 +2,7 @@ ## Broadcast styles import Base.Broadcast -using Base.Broadcast: DefaultArrayStyle, Broadcasted, tail +using Base.Broadcast: DefaultArrayStyle, Broadcasted struct StructuredMatrixStyle{T} <: Broadcast.AbstractArrayStyle{2} end StructuredMatrixStyle{T}(::Val{2}) where {T} = StructuredMatrixStyle{T}() diff --git a/stdlib/REPL/src/LineEdit.jl b/stdlib/REPL/src/LineEdit.jl index 9f1dd76b168af..3b63a256dafe2 100644 --- a/stdlib/REPL/src/LineEdit.jl +++ b/stdlib/REPL/src/LineEdit.jl @@ -6,8 +6,7 @@ import ..REPL using REPL: AbstractREPL, Options using ..Terminals -import ..Terminals: raw!, width, height, cmove, getX, - getY, clear_line, beep +import ..Terminals: raw!, width, height, clear_line, beep import Base: ensureroom, show, AnyDict, position using Base: something diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index 840e6daaf1909..c5c45dee34a01 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -130,12 +130,10 @@ import ..LineEdit: history_first, history_last, history_search, - accept_result, setmodifiers!, terminal, MIState, PromptState, - TextInterface, mode_idx include("REPLCompletions.jl") diff --git a/stdlib/REPL/src/REPLCompletions.jl b/stdlib/REPL/src/REPLCompletions.jl index 621cd6f9021fb..609825b772d47 100644 --- a/stdlib/REPL/src/REPLCompletions.jl +++ b/stdlib/REPL/src/REPLCompletions.jl @@ -4,7 +4,7 @@ module REPLCompletions export completions, shell_completions, bslash_completions, completion_text -using Core: CodeInfo, MethodInstance, CodeInstance, Const +using Core: Const const CC = Core.Compiler using Base.Meta using Base: propertynames, something, IdSet diff --git a/stdlib/REPL/src/Terminals.jl b/stdlib/REPL/src/Terminals.jl index dac19406b3fc1..821ed224f1829 100644 --- a/stdlib/REPL/src/Terminals.jl +++ b/stdlib/REPL/src/Terminals.jl @@ -30,9 +30,7 @@ import Base: displaysize, flush, pipe_reader, - pipe_writer, - read, - readuntil + pipe_writer ## AbstractTerminal: abstract supertype of all terminals ## diff --git a/stdlib/Serialization/src/Serialization.jl b/stdlib/Serialization/src/Serialization.jl index 7f122142c1fff..2e1d4cd801fd9 100644 --- a/stdlib/Serialization/src/Serialization.jl +++ b/stdlib/Serialization/src/Serialization.jl @@ -7,7 +7,7 @@ Provide serialization of Julia objects via the functions """ module Serialization -import Base: GMP, Bottom, unsafe_convert +import Base: Bottom, unsafe_convert import Core: svec, SimpleVector using Base: unaliascopy, unwrap_unionall, require_one_based_indexing, ntupleany using Core.IR diff --git a/stdlib/Sockets/src/Sockets.jl b/stdlib/Sockets/src/Sockets.jl index 85f3e7639b6ae..5baf8826cc883 100644 --- a/stdlib/Sockets/src/Sockets.jl +++ b/stdlib/Sockets/src/Sockets.jl @@ -31,7 +31,7 @@ export IPv4, IPv6 -import Base: isless, show, print, parse, bind, convert, isreadable, iswritable, alloc_buf_hook, _uv_hook_close +import Base: isless, show, print, parse, bind, alloc_buf_hook, _uv_hook_close using Base: LibuvStream, LibuvServer, PipeEndpoint, @handle_as, uv_error, associate_julia_struct, uvfinalize, notify_error, uv_req_data, uv_req_set_data, preserve_handle, unpreserve_handle, _UVError, IOError, From b18824a9282b216a5e2b2e8d0cbb941a013154cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Mon, 26 Feb 2024 08:18:52 +0000 Subject: [PATCH 06/13] Wrap `contrib/check-whitespace.jl` in a function (#53468) --- contrib/check-whitespace.jl | 62 ++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/contrib/check-whitespace.jl b/contrib/check-whitespace.jl index b92f0c88a53a6..e178ec8a02a38 100755 --- a/contrib/check-whitespace.jl +++ b/contrib/check-whitespace.jl @@ -32,39 +32,43 @@ allow_tabs(path) = const errors = Set{Tuple{String,Int,String}}() -for path in eachline(`git ls-files -- $patterns`) - lineno = 0 - non_blank = 0 +function check_whitespace() + for path in eachline(`git ls-files -- $patterns`) + lineno = 0 + non_blank = 0 - file_err(msg) = push!(errors, (path, 0, msg)) - line_err(msg) = push!(errors, (path, lineno, msg)) + file_err(msg) = push!(errors, (path, 0, msg)) + line_err(msg) = push!(errors, (path, lineno, msg)) - isfile(path) || continue - for line in eachline(path, keep=true) - lineno += 1 - contains(line, '\r') && file_err("non-UNIX line endings") - contains(line, '\ua0') && line_err("non-breaking space") - allow_tabs(path) || - contains(line, '\t') && line_err("tab") - endswith(line, '\n') || line_err("no trailing newline") - line = chomp(line) - endswith(line, r"\s") && line_err("trailing whitespace") - contains(line, r"\S") && (non_blank = lineno) + isfile(path) || continue + for line in eachline(path, keep=true) + lineno += 1 + contains(line, '\r') && file_err("non-UNIX line endings") + contains(line, '\ua0') && line_err("non-breaking space") + allow_tabs(path) || + contains(line, '\t') && line_err("tab") + endswith(line, '\n') || line_err("no trailing newline") + line = chomp(line) + endswith(line, r"\s") && line_err("trailing whitespace") + contains(line, r"\S") && (non_blank = lineno) + end + non_blank < lineno && line_err("trailing blank lines") end - non_blank < lineno && line_err("trailing blank lines") -end -if isempty(errors) - println(stderr, "Whitespace check found no issues.") - exit(0) -else - println(stderr, "Whitespace check found $(length(errors)) issues:") - for (path, lineno, msg) in sort!(collect(errors)) - if lineno == 0 - println(stderr, "$path -- $msg") - else - println(stderr, "$path:$lineno -- $msg") + if isempty(errors) + println(stderr, "Whitespace check found no issues.") + exit(0) + else + println(stderr, "Whitespace check found $(length(errors)) issues:") + for (path, lineno, msg) in sort!(collect(errors)) + if lineno == 0 + println(stderr, "$path -- $msg") + else + println(stderr, "$path:$lineno -- $msg") + end end + exit(1) end - exit(1) end + +check_whitespace() From 3ebba8f6d152970045a9d5b03519855ae633b725 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Mon, 26 Feb 2024 06:06:32 -0800 Subject: [PATCH 07/13] use ScopedValues for MPFR precision and rounding (#51362) Should fix thread safety issues. Actually fixes #27139 --- base/mpfr.jl | 174 ++++++++++++++++++++++++++------------------------- 1 file changed, 90 insertions(+), 84 deletions(-) diff --git a/base/mpfr.jl b/base/mpfr.jl index c12154fa517c3..d3045371829f6 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -109,8 +109,9 @@ end tie_breaker_is_to_even(::MPFRRoundingMode) = true const ROUNDING_MODE = Ref{MPFRRoundingMode}(MPFRRoundNearest) +const CURRENT_ROUNDING_MODE = ScopedValue{MPFRRoundingMode}() const DEFAULT_PRECISION = Ref{Clong}(256) - +const CURRENT_PRECISION = ScopedValue{Clong}() # Basic type and initialization definitions # Warning: the constants are MPFR implementation details from @@ -144,7 +145,7 @@ mutable struct BigFloat <: AbstractFloat return new(prec, sign, exp, pointer(d), d) end - function BigFloat(; precision::Integer=DEFAULT_PRECISION[]) + function BigFloat(; precision::Integer=_precision_with_base_2(BigFloat)) precision < 1 && throw(DomainError(precision, "`precision` cannot be less than 1.")) nb = ccall((:mpfr_custom_get_size,libmpfr), Csize_t, (Clong,), precision) nb = (nb + Core.sizeof(Limb) - 1) รท Core.sizeof(Limb) # align to number of Limb allocations required for this @@ -158,11 +159,17 @@ end # The rounding mode here shouldn't matter. significand_limb_count(x::BigFloat) = div(sizeof(x._d), sizeof(Limb), RoundToZero) -rounding_raw(::Type{BigFloat}) = ROUNDING_MODE[] +rounding_raw(::Type{BigFloat}) = something(Base.ScopedValues.get(CURRENT_ROUNDING_MODE), ROUNDING_MODE[]) setrounding_raw(::Type{BigFloat}, r::MPFRRoundingMode) = ROUNDING_MODE[]=r +function setrounding_raw(f::Function, ::Type{BigFloat}, r::MPFRRoundingMode) + @with(CURRENT_ROUNDING_MODE => r, f()) +end + rounding(::Type{BigFloat}) = convert(RoundingMode, rounding_raw(BigFloat)) setrounding(::Type{BigFloat}, r::RoundingMode) = setrounding_raw(BigFloat, convert(MPFRRoundingMode, r)) +setrounding(f::Function, ::Type{BigFloat}, r::RoundingMode) = + setrounding_raw(f, BigFloat, convert(MPFRRoundingMode, r)) # overload the definition of unsafe_convert to ensure that `x.d` is assigned @@ -220,7 +227,7 @@ BigFloat(x, r::RoundingMode) widen(::Type{Float64}) = BigFloat widen(::Type{BigFloat}) = BigFloat -function BigFloat(x::BigFloat, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) +function BigFloat(x::BigFloat, r::MPFRRoundingMode=rounding_raw(BigFloat); precision::Integer=_precision_with_base_2(BigFloat)) if precision == _precision_with_base_2(x) return x else @@ -240,7 +247,7 @@ end # convert to BigFloat for (fJ, fC) in ((:si,:Clong), (:ui,:Culong)) @eval begin - function BigFloat(x::($fC), r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) + function BigFloat(x::($fC), r::MPFRRoundingMode=rounding_raw(BigFloat); precision::Integer=_precision_with_base_2(BigFloat)) z = BigFloat(;precision=precision) ccall(($(string(:mpfr_set_,fJ)), libmpfr), Int32, (Ref{BigFloat}, $fC, MPFRRoundingMode), z, x, r) return z @@ -248,7 +255,7 @@ for (fJ, fC) in ((:si,:Clong), (:ui,:Culong)) end end -function BigFloat(x::Float64, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) +function BigFloat(x::Float64, r::MPFRRoundingMode=rounding_raw(BigFloat); precision::Integer=_precision_with_base_2(BigFloat)) z = BigFloat(;precision) # punt on the hard case where we might have to deal with rounding # we could use this path in all cases, but mpfr_set_d has a lot of overhead. @@ -291,26 +298,26 @@ function BigFloat(x::Float64, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::In z end -function BigFloat(x::BigInt, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) +function BigFloat(x::BigInt, r::MPFRRoundingMode=rounding_raw(BigFloat); precision::Integer=_precision_with_base_2(BigFloat)) z = BigFloat(;precision=precision) ccall((:mpfr_set_z, libmpfr), Int32, (Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, r) return z end -BigFloat(x::Integer; precision::Integer=DEFAULT_PRECISION[]) = - BigFloat(BigInt(x)::BigInt, ROUNDING_MODE[]; precision=precision) -BigFloat(x::Integer, r::MPFRRoundingMode; precision::Integer=DEFAULT_PRECISION[]) = +BigFloat(x::Integer; precision::Integer=_precision_with_base_2(BigFloat)) = + BigFloat(BigInt(x)::BigInt, rounding_raw(BigFloat); precision=precision) +BigFloat(x::Integer, r::MPFRRoundingMode; precision::Integer=_precision_with_base_2(BigFloat)) = BigFloat(BigInt(x)::BigInt, r; precision=precision) -BigFloat(x::Union{Bool,Int8,Int16,Int32}, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) = +BigFloat(x::Union{Bool,Int8,Int16,Int32}, r::MPFRRoundingMode=rounding_raw(BigFloat); precision::Integer=_precision_with_base_2(BigFloat)) = BigFloat(convert(Clong, x), r; precision=precision) -BigFloat(x::Union{UInt8,UInt16,UInt32}, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) = +BigFloat(x::Union{UInt8,UInt16,UInt32}, r::MPFRRoundingMode=rounding_raw(BigFloat); precision::Integer=_precision_with_base_2(BigFloat)) = BigFloat(convert(Culong, x), r; precision=precision) -BigFloat(x::Union{Float16,Float32}, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) = +BigFloat(x::Union{Float16,Float32}, r::MPFRRoundingMode=rounding_raw(BigFloat); precision::Integer=_precision_with_base_2(BigFloat)) = BigFloat(Float64(x), r; precision=precision) -function BigFloat(x::Rational, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) +function BigFloat(x::Rational, r::MPFRRoundingMode=rounding_raw(BigFloat); precision::Integer=_precision_with_base_2(BigFloat)) setprecision(BigFloat, precision) do setrounding_raw(BigFloat, r) do BigFloat(numerator(x))::BigFloat / BigFloat(denominator(x))::BigFloat @@ -318,14 +325,14 @@ function BigFloat(x::Rational, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::I end end -function tryparse(::Type{BigFloat}, s::AbstractString; base::Integer=0, precision::Integer=DEFAULT_PRECISION[], rounding::MPFRRoundingMode=ROUNDING_MODE[]) +function tryparse(::Type{BigFloat}, s::AbstractString; base::Integer=0, precision::Integer=_precision_with_base_2(BigFloat), rounding::MPFRRoundingMode=rounding_raw(BigFloat)) !isempty(s) && isspace(s[end]) && return tryparse(BigFloat, rstrip(s), base = base) z = BigFloat(precision=precision) err = ccall((:mpfr_set_str, libmpfr), Int32, (Ref{BigFloat}, Cstring, Int32, MPFRRoundingMode), z, s, base, rounding) err == 0 ? z : nothing end -BigFloat(x::AbstractString, r::MPFRRoundingMode=ROUNDING_MODE[]; precision::Integer=DEFAULT_PRECISION[]) = +BigFloat(x::AbstractString, r::MPFRRoundingMode=rounding_raw(BigFloat); precision::Integer=_precision_with_base_2(BigFloat)) = parse(BigFloat, x; precision=precision, rounding=r) Rational(x::BigFloat) = convert(Rational{BigInt}, x) @@ -333,9 +340,9 @@ AbstractFloat(x::BigInt) = BigFloat(x) float(::Type{BigInt}) = BigFloat -BigFloat(x::Real, r::RoundingMode; precision::Integer=DEFAULT_PRECISION[]) = +BigFloat(x::Real, r::RoundingMode; precision::Integer=_precision_with_base_2(BigFloat)) = BigFloat(x, convert(MPFRRoundingMode, r); precision=precision)::BigFloat -BigFloat(x::AbstractString, r::RoundingMode; precision::Integer=DEFAULT_PRECISION[]) = +BigFloat(x::AbstractString, r::RoundingMode; precision::Integer=_precision_with_base_2(BigFloat)) = BigFloat(x, convert(MPFRRoundingMode, r); precision=precision) ## BigFloat -> Integer @@ -385,7 +392,7 @@ round(::Type{BigInt}, x::BigFloat, r::RoundingMode) = unsafe_trunc(::Type{T}, x::BigFloat) where {T<:Integer} = unsafe_trunc(T, _unchecked_cast(T, x, RoundToZero)) unsafe_trunc(::Type{BigInt}, x::BigFloat) = _unchecked_cast(BigInt, x, RoundToZero) -round(::Type{T}, x::BigFloat) where T<:Integer = round(T, x, ROUNDING_MODE[]) +round(::Type{T}, x::BigFloat) where T<:Integer = round(T, x, rounding_raw(BigFloat)) # these two methods are split to increase their precedence in disambiguation: round(::Type{Integer}, x::BigFloat, r::RoundingMode) = round(BigInt, x, r) round(::Type{Integer}, x::BigFloat, r::MPFRRoundingMode) = round(BigInt, x, r) @@ -461,9 +468,9 @@ function to_ieee754(::Type{T}, x::BigFloat, rm) where {T<:AbstractFloat} reinterpret(T, ret_u) end -Float16(x::BigFloat, r::MPFRRoundingMode=ROUNDING_MODE[]) = to_ieee754(Float16, x, r) -Float32(x::BigFloat, r::MPFRRoundingMode=ROUNDING_MODE[]) = to_ieee754(Float32, x, r) -Float64(x::BigFloat, r::MPFRRoundingMode=ROUNDING_MODE[]) = to_ieee754(Float64, x, r) +Float16(x::BigFloat, r::MPFRRoundingMode=rounding_raw(BigFloat)) = to_ieee754(Float16, x, r) +Float32(x::BigFloat, r::MPFRRoundingMode=rounding_raw(BigFloat)) = to_ieee754(Float32, x, r) +Float64(x::BigFloat, r::MPFRRoundingMode=rounding_raw(BigFloat)) = to_ieee754(Float64, x, r) Float16(x::BigFloat, r::RoundingMode) = to_ieee754(Float16, x, r) Float32(x::BigFloat, r::RoundingMode) = to_ieee754(Float32, x, r) Float64(x::BigFloat, r::RoundingMode) = to_ieee754(Float64, x, r) @@ -490,14 +497,14 @@ for (fJ, fC) in ((:+,:add), (:*,:mul)) # BigFloat function ($fJ)(x::BigFloat, y::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,fC)),libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)),libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, rounding_raw(BigFloat)) return z end # Unsigned Integer function ($fJ)(x::BigFloat, c::CulongMax) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_ui)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_ui)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, c, rounding_raw(BigFloat)) return z end ($fJ)(c::CulongMax, x::BigFloat) = ($fJ)(x,c) @@ -505,7 +512,7 @@ for (fJ, fC) in ((:+,:add), (:*,:mul)) # Signed Integer function ($fJ)(x::BigFloat, c::ClongMax) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_si)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_si)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, c, rounding_raw(BigFloat)) return z end ($fJ)(c::ClongMax, x::BigFloat) = ($fJ)(x,c) @@ -513,7 +520,7 @@ for (fJ, fC) in ((:+,:add), (:*,:mul)) # Float32/Float64 function ($fJ)(x::BigFloat, c::CdoubleMax) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_d)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Cdouble, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_d)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Cdouble, MPFRRoundingMode), z, x, c, rounding_raw(BigFloat)) return z end ($fJ)(c::CdoubleMax, x::BigFloat) = ($fJ)(x,c) @@ -521,7 +528,7 @@ for (fJ, fC) in ((:+,:add), (:*,:mul)) # BigInt function ($fJ)(x::BigFloat, c::BigInt) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_z)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_z)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, c, rounding_raw(BigFloat)) return z end ($fJ)(c::BigInt, x::BigFloat) = ($fJ)(x,c) @@ -533,50 +540,50 @@ for (fJ, fC) in ((:-,:sub), (:/,:div)) # BigFloat function ($fJ)(x::BigFloat, y::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,fC)),libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)),libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, rounding_raw(BigFloat)) return z end # Unsigned Int function ($fJ)(x::BigFloat, c::CulongMax) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_ui)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_ui)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, c, rounding_raw(BigFloat)) return z end function ($fJ)(c::CulongMax, x::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,:ui_,fC)), libmpfr), Int32, (Ref{BigFloat}, Culong, Ref{BigFloat}, MPFRRoundingMode), z, c, x, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,:ui_,fC)), libmpfr), Int32, (Ref{BigFloat}, Culong, Ref{BigFloat}, MPFRRoundingMode), z, c, x, rounding_raw(BigFloat)) return z end # Signed Integer function ($fJ)(x::BigFloat, c::ClongMax) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_si)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_si)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, c, rounding_raw(BigFloat)) return z end function ($fJ)(c::ClongMax, x::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,:si_,fC)), libmpfr), Int32, (Ref{BigFloat}, Clong, Ref{BigFloat}, MPFRRoundingMode), z, c, x, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,:si_,fC)), libmpfr), Int32, (Ref{BigFloat}, Clong, Ref{BigFloat}, MPFRRoundingMode), z, c, x, rounding_raw(BigFloat)) return z end # Float32/Float64 function ($fJ)(x::BigFloat, c::CdoubleMax) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_d)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Cdouble, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_d)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Cdouble, MPFRRoundingMode), z, x, c, rounding_raw(BigFloat)) return z end function ($fJ)(c::CdoubleMax, x::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,:d_,fC)), libmpfr), Int32, (Ref{BigFloat}, Cdouble, Ref{BigFloat}, MPFRRoundingMode), z, c, x, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,:d_,fC)), libmpfr), Int32, (Ref{BigFloat}, Cdouble, Ref{BigFloat}, MPFRRoundingMode), z, c, x, rounding_raw(BigFloat)) return z end # BigInt function ($fJ)(x::BigFloat, c::BigInt) z = BigFloat() - ccall(($(string(:mpfr_,fC,:_z)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC,:_z)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, c, rounding_raw(BigFloat)) return z end # no :mpfr_z_div function @@ -585,7 +592,7 @@ end function -(c::BigInt, x::BigFloat) z = BigFloat() - ccall((:mpfr_z_sub, libmpfr), Int32, (Ref{BigFloat}, Ref{BigInt}, Ref{BigFloat}, MPFRRoundingMode), z, c, x, ROUNDING_MODE[]) + ccall((:mpfr_z_sub, libmpfr), Int32, (Ref{BigFloat}, Ref{BigInt}, Ref{BigFloat}, MPFRRoundingMode), z, c, x, rounding_raw(BigFloat)) return z end @@ -593,7 +600,7 @@ inv(x::BigFloat) = one(Clong) / x # faster than fallback one(x)/x function fma(x::BigFloat, y::BigFloat, z::BigFloat) r = BigFloat() - ccall(("mpfr_fma",libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), r, x, y, z, ROUNDING_MODE[]) + ccall(("mpfr_fma",libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), r, x, y, z, rounding_raw(BigFloat)) return r end @@ -664,23 +671,23 @@ for (fJ, fC, fI) in ((:+, :add, 0), (:*, :mul, 1)) @eval begin function ($fJ)(a::BigFloat, b::BigFloat, c::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, a, b, ROUNDING_MODE[]) - ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, c, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, a, b, rounding_raw(BigFloat)) + ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, c, rounding_raw(BigFloat)) return z end function ($fJ)(a::BigFloat, b::BigFloat, c::BigFloat, d::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, a, b, ROUNDING_MODE[]) - ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, c, ROUNDING_MODE[]) - ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, d, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, a, b, rounding_raw(BigFloat)) + ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, c, rounding_raw(BigFloat)) + ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, d, rounding_raw(BigFloat)) return z end function ($fJ)(a::BigFloat, b::BigFloat, c::BigFloat, d::BigFloat, e::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, a, b, ROUNDING_MODE[]) - ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, c, ROUNDING_MODE[]) - ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, d, ROUNDING_MODE[]) - ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, e, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, a, b, rounding_raw(BigFloat)) + ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, c, rounding_raw(BigFloat)) + ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, d, rounding_raw(BigFloat)) + ccall(($(string(:mpfr_,fC)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, e, rounding_raw(BigFloat)) return z end end @@ -688,14 +695,14 @@ end function -(x::BigFloat) z = BigFloat() - ccall((:mpfr_neg, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) + ccall((:mpfr_neg, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, rounding_raw(BigFloat)) return z end function sqrt(x::BigFloat) isnan(x) && return x z = BigFloat() - ccall((:mpfr_sqrt, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) + ccall((:mpfr_sqrt, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, rounding_raw(BigFloat)) isnan(z) && throw(DomainError(x, "NaN result for non-NaN input.")) return z end @@ -704,25 +711,25 @@ sqrt(x::BigInt) = sqrt(BigFloat(x)) function ^(x::BigFloat, y::BigFloat) z = BigFloat() - ccall((:mpfr_pow, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_pow, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, rounding_raw(BigFloat)) return z end function ^(x::BigFloat, y::CulongMax) z = BigFloat() - ccall((:mpfr_pow_ui, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_pow_ui, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, y, rounding_raw(BigFloat)) return z end function ^(x::BigFloat, y::ClongMax) z = BigFloat() - ccall((:mpfr_pow_si, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_pow_si, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, y, rounding_raw(BigFloat)) return z end function ^(x::BigFloat, y::BigInt) z = BigFloat() - ccall((:mpfr_pow_z, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_pow_z, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigInt}, MPFRRoundingMode), z, x, y, rounding_raw(BigFloat)) return z end @@ -732,7 +739,7 @@ end for f in (:exp, :exp2, :exp10, :expm1, :cosh, :sinh, :tanh, :sech, :csch, :coth, :cbrt) @eval function $f(x::BigFloat) z = BigFloat() - ccall(($(string(:mpfr_,f)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,f)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, rounding_raw(BigFloat)) return z end end @@ -740,7 +747,7 @@ end function sincos_fast(v::BigFloat) s = BigFloat() c = BigFloat() - ccall((:mpfr_sin_cos, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), s, c, v, ROUNDING_MODE[]) + ccall((:mpfr_sin_cos, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), s, c, v, rounding_raw(BigFloat)) return (s, c) end sincos(v::BigFloat) = sincos_fast(v) @@ -748,18 +755,18 @@ sincos(v::BigFloat) = sincos_fast(v) # return log(2) function big_ln2() c = BigFloat() - ccall((:mpfr_const_log2, libmpfr), Cint, (Ref{BigFloat}, MPFRRoundingMode), c, MPFR.ROUNDING_MODE[]) + ccall((:mpfr_const_log2, libmpfr), Cint, (Ref{BigFloat}, MPFRRoundingMode), c, MPFR.rounding_raw(BigFloat)) return c end function ldexp(x::BigFloat, n::Clong) z = BigFloat() - ccall((:mpfr_mul_2si, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, n, ROUNDING_MODE[]) + ccall((:mpfr_mul_2si, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, x, n, rounding_raw(BigFloat)) return z end function ldexp(x::BigFloat, n::Culong) z = BigFloat() - ccall((:mpfr_mul_2ui, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, n, ROUNDING_MODE[]) + ccall((:mpfr_mul_2ui, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, n, rounding_raw(BigFloat)) return z end ldexp(x::BigFloat, n::ClongMax) = ldexp(x, convert(Clong, n)) @@ -772,13 +779,13 @@ function factorial(x::BigFloat) end ui = convert(Culong, x) z = BigFloat() - ccall((:mpfr_fac_ui, libmpfr), Int32, (Ref{BigFloat}, Culong, MPFRRoundingMode), z, ui, ROUNDING_MODE[]) + ccall((:mpfr_fac_ui, libmpfr), Int32, (Ref{BigFloat}, Culong, MPFRRoundingMode), z, ui, rounding_raw(BigFloat)) return z end function hypot(x::BigFloat, y::BigFloat) z = BigFloat() - ccall((:mpfr_hypot, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_hypot, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, rounding_raw(BigFloat)) return z end @@ -790,7 +797,7 @@ for f in (:log, :log2, :log10) "with a complex argument. Try ", $f, "(complex(x))."))) end z = BigFloat() - ccall(($(string(:mpfr_,f)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,f)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, rounding_raw(BigFloat)) return z end end @@ -802,7 +809,7 @@ function log1p(x::BigFloat) "with a complex argument. Try log1p(complex(x))."))) end z = BigFloat() - ccall((:mpfr_log1p, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) + ccall((:mpfr_log1p, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, rounding_raw(BigFloat)) return z end @@ -826,19 +833,19 @@ end function modf(x::BigFloat) zint = BigFloat() zfloat = BigFloat() - ccall((:mpfr_modf, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), zint, zfloat, x, ROUNDING_MODE[]) + ccall((:mpfr_modf, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), zint, zfloat, x, rounding_raw(BigFloat)) return (zfloat, zint) end function rem(x::BigFloat, y::BigFloat) z = BigFloat() - ccall((:mpfr_fmod, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_fmod, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, rounding_raw(BigFloat)) return z end function rem(x::BigFloat, y::BigFloat, ::RoundingMode{:Nearest}) z = BigFloat() - ccall((:mpfr_remainder, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_remainder, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, rounding_raw(BigFloat)) return z end @@ -849,7 +856,7 @@ function sum(arr::AbstractArray{BigFloat}) z = BigFloat(0) for i in arr ccall((:mpfr_add, libmpfr), Int32, - (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, i, ROUNDING_MODE[]) + (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, z, i, rounding_raw(BigFloat)) end return z end @@ -860,7 +867,7 @@ for f in (:sin, :cos, :tan, :sec, :csc, :acos, :asin, :atan, :acosh, :asinh, :at function ($f)(x::BigFloat) isnan(x) && return x z = BigFloat() - ccall(($(string(:mpfr_,f)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,f)), libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, rounding_raw(BigFloat)) isnan(z) && throw(DomainError(x, "NaN result for non-NaN input.")) return z end @@ -870,7 +877,7 @@ sincospi(x::BigFloat) = (sinpi(x), cospi(x)) function atan(y::BigFloat, x::BigFloat) z = BigFloat() - ccall((:mpfr_atan2, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, y, x, ROUNDING_MODE[]) + ccall((:mpfr_atan2, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, y, x, rounding_raw(BigFloat)) return z end @@ -880,14 +887,14 @@ for f in (:sin, :cos, :tan) function ($(Symbol(f,:d)))(x::BigFloat) isnan(x) && return x z = BigFloat() - ccall(($(string(:mpfr_,f,:u)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, 360, ROUNDING_MODE[]) + ccall(($(string(:mpfr_,f,:u)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, 360, rounding_raw(BigFloat)) isnan(z) && throw(DomainError(x, "NaN result for non-NaN input.")) return z end function ($(Symbol(:a,f,:d)))(x::BigFloat) isnan(x) && return x z = BigFloat() - ccall(($(string(:mpfr_a,f,:u)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, 360, ROUNDING_MODE[]) + ccall(($(string(:mpfr_a,f,:u)), :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, x, 360, rounding_raw(BigFloat)) isnan(z) && throw(DomainError(x, "NaN result for non-NaN input.")) return z end @@ -895,7 +902,7 @@ for f in (:sin, :cos, :tan) end function atand(y::BigFloat, x::BigFloat) z = BigFloat() - ccall((:mpfr_atan2u, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, y, x, 360, ROUNDING_MODE[]) + ccall((:mpfr_atan2u, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode), z, y, x, 360, rounding_raw(BigFloat)) return z end @@ -959,7 +966,12 @@ function _precision_with_base_2(x::BigFloat) # precision of an object of type B end precision(x::BigFloat; base::Integer=2) = _precision(x, base) -_precision_with_base_2(::Type{BigFloat}) = Int(DEFAULT_PRECISION[]) # default precision of the type BigFloat itself + +_convert_precision_from_base(precision::Integer, base::Integer) = + base == 2 ? precision : ceil(Int, precision * log2(base)) + +_precision_with_base_2(::Type{BigFloat}) = + Int(something(Base.ScopedValues.get(CURRENT_PRECISION), DEFAULT_PRECISION[])) # default precision of the type BigFloat itself """ setprecision([T=BigFloat,] precision::Int; base=2) @@ -980,7 +992,7 @@ at least `precision` digits in the given `base`. function setprecision(::Type{BigFloat}, precision::Integer; base::Integer=2) base > 1 || throw(DomainError(base, "`base` cannot be less than 2.")) precision > 0 || throw(DomainError(precision, "`precision` cannot be less than 1.")) - DEFAULT_PRECISION[] = base == 2 ? precision : ceil(Int, precision * log2(base)) + DEFAULT_PRECISION[] = _convert_precision_from_base(precision, base) return precision end @@ -991,7 +1003,7 @@ maxintfloat(::Type{BigFloat}) = BigFloat(2)^precision(BigFloat) function copysign(x::BigFloat, y::BigFloat) z = BigFloat() - ccall((:mpfr_copysign, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, ROUNDING_MODE[]) + ccall((:mpfr_copysign, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), z, x, y, rounding_raw(BigFloat)) return z end @@ -1006,16 +1018,16 @@ end function frexp(x::BigFloat) z = BigFloat() c = Ref{Clong}() - ccall((:mpfr_frexp, libmpfr), Int32, (Ptr{Clong}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), c, z, x, ROUNDING_MODE[]) + ccall((:mpfr_frexp, libmpfr), Int32, (Ptr{Clong}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), c, z, x, rounding_raw(BigFloat)) return (z, c[]) end function significand(x::BigFloat) z = BigFloat() c = Ref{Clong}() - ccall((:mpfr_frexp, libmpfr), Int32, (Ptr{Clong}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), c, z, x, ROUNDING_MODE[]) + ccall((:mpfr_frexp, libmpfr), Int32, (Ptr{Clong}, Ref{BigFloat}, Ref{BigFloat}, MPFRRoundingMode), c, z, x, rounding_raw(BigFloat)) # Double the significand to make it work as Base.significand - ccall((:mpfr_mul_si, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, z, 2, ROUNDING_MODE[]) + ccall((:mpfr_mul_si, libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Clong, MPFRRoundingMode), z, z, 2, rounding_raw(BigFloat)) return z end @@ -1096,14 +1108,8 @@ Note: `nextfloat()`, `prevfloat()` do not use the precision mentioned by !!! compat "Julia 1.8" The `base` keyword requires at least Julia 1.8. """ -function setprecision(f::Function, ::Type{T}, prec::Integer; kws...) where T - old_prec = precision(T) - setprecision(T, prec; kws...) - try - return f() - finally - setprecision(T, old_prec) - end +function setprecision(f::Function, ::Type{BigFloat}, prec::Integer; base::Integer=2) + @with(CURRENT_PRECISION => _convert_precision_from_base(prec, base), f()) end setprecision(f::Function, prec::Integer; base::Integer=2) = setprecision(f, BigFloat, prec; base) From 4634c743d20603873c2b0c9f3d6d5b71a6fd1853 Mon Sep 17 00:00:00 2001 From: Alexander Plavin Date: Mon, 26 Feb 2024 14:17:38 -0500 Subject: [PATCH 08/13] add array `typeinfo` support for NamedTuples (#53465) Closes https://github.com/JuliaLang/julia/issues/53455 --- base/arrayshow.jl | 2 +- test/show.jl | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/base/arrayshow.jl b/base/arrayshow.jl index db639a88876e8..164a9257d8412 100644 --- a/base/arrayshow.jl +++ b/base/arrayshow.jl @@ -554,7 +554,7 @@ function typeinfo_implicit(@nospecialize(T)) end return isconcretetype(T) && ((T <: Array && typeinfo_implicit(eltype(T))) || - ((T <: Tuple || T <: Pair) && all(typeinfo_implicit, fieldtypes(T))) || + ((T <: Tuple || T <: NamedTuple || T <: Pair) && all(typeinfo_implicit, fieldtypes(T))) || (T <: AbstractDict && typeinfo_implicit(keytype(T)) && typeinfo_implicit(valtype(T)))) end diff --git a/test/show.jl b/test/show.jl index 66286f4df12ba..064ae76b6fe1f 100644 --- a/test/show.jl +++ b/test/show.jl @@ -1892,6 +1892,7 @@ end @test showstr(Pair{Integer,Integer}(1, 2), :typeinfo => Pair{Integer,Integer}) == "1 => 2" @test showstr([Pair{Integer,Integer}(1, 2)]) == "Pair{Integer, Integer}[1 => 2]" + @test showstr([(a=1,)]) == "[(a = 1,)]" @test showstr(Dict{Integer,Integer}(1 => 2)) == "Dict{Integer, Integer}(1 => 2)" @test showstr(Dict(true=>false)) == "Dict{Bool, Bool}(1 => 0)" @test showstr(Dict((1 => 2) => (3 => 4))) == "Dict((1 => 2) => (3 => 4))" From a796a41766c19e3daf004e0a6d7828cf09841d27 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Mon, 26 Feb 2024 14:52:42 -0500 Subject: [PATCH 09/13] add suffix kwarg to `tempname` (#53474) `tempname` checks that the name its returning is not already a file, however if you want that filename to contain other information, like a file extension, that can mean the uniquing isn't complete. This adds `tempname(suffix = "_foo.txt")` to include a suffix in the name and uniquing check. --------- Co-authored-by: Jameson Nash --- NEWS.md | 3 +++ base/file.jl | 12 ++++++++---- test/file.jl | 3 +++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/NEWS.md b/NEWS.md index 6b5fd28082b9b..c37cb9efdd9b8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -27,6 +27,9 @@ New library functions New library features -------------------- +* `tempname` can now take a suffix string to allow the file name to include a suffix and include that suffix in + the uniquing checking ([#53474]) + Standard library changes ------------------------ diff --git a/base/file.jl b/base/file.jl index 6347f042e3422..6156bafacdc47 100644 --- a/base/file.jl +++ b/base/file.jl @@ -620,13 +620,13 @@ end # Obtain a temporary filename. -function tempname(parent::AbstractString=tempdir(); max_tries::Int = 100, cleanup::Bool=true) +function tempname(parent::AbstractString=tempdir(); max_tries::Int = 100, cleanup::Bool=true, suffix::AbstractString="") isdir(parent) || throw(ArgumentError("$(repr(parent)) is not a directory")) prefix = joinpath(parent, temp_prefix) filename = nothing for i in 1:max_tries - filename = string(prefix, _rand_filename()) + filename = string(prefix, _rand_filename(), suffix) if ispath(filename) filename = nothing else @@ -682,7 +682,7 @@ end # os-test """ - tempname(parent=tempdir(); cleanup=true) -> String + tempname(parent=tempdir(); cleanup=true, suffix="") -> String Generate a temporary file path. This function only returns a path; no file is created. The path is likely to be unique, but this cannot be guaranteed due to @@ -693,7 +693,8 @@ existing at the time of the call to `tempname`. When called with no arguments, the temporary name will be an absolute path to a temporary name in the system temporary directory as given by `tempdir()`. If a `parent` directory argument is given, the temporary path will be in that -directory instead. +directory instead. If a suffix is given the tempname will end with that suffix +and be tested for uniqueness with that suffix. The `cleanup` option controls whether the process attempts to delete the returned path automatically when the process exits. Note that the `tempname` @@ -705,6 +706,9 @@ you do and `cleanup` is `true` it will be deleted upon process termination. The `parent` and `cleanup` arguments were added in 1.4. Prior to Julia 1.4 the path `tempname` would never be cleaned up at process termination. +!!! compat "Julia 1.12" + The `suffix` keyword argument was added in Julia 1.12. + !!! warning This can lead to security holes if another process obtains the same diff --git a/test/file.jl b/test/file.jl index e0241c5ef38df..1ce7a5cdb440b 100644 --- a/test/file.jl +++ b/test/file.jl @@ -124,6 +124,9 @@ end end @test_throws ArgumentError tempname(randstring()) end +@testset "tempname with suffix" begin + @test !isfile(tempname(suffix = "_foo.txt")) +end child_eval(code::String) = eval(Meta.parse(readchomp(`$(Base.julia_cmd()) -E $code`))) From 189a255ecfc98ddd1f16ee9d0cea5c98b6c19432 Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Mon, 26 Feb 2024 15:18:44 -0500 Subject: [PATCH 10/13] =?UTF-8?q?=F0=9F=A4=96=20[master]=20Bump=20the=20Di?= =?UTF-8?q?stributed=20stdlib=20from=2041c0106=20to=206a07d98=20(#53477)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stdlib: Distributed URL: https://github.com/JuliaLang/Distributed.jl Stdlib branch: master Julia branch: master Old commit: 41c0106 New commit: 6a07d98 Julia version: 1.12.0-DEV Distributed version: 1.11.0(Does not match) Bump invoked by: @IanButterworth Powered by: [BumpStdlibs.jl](https://github.com/JuliaLang/BumpStdlibs.jl) Diff: https://github.com/JuliaLang/Distributed.jl/compare/41c01069533e22a6ce6b794746e4b3aa9f5a25cd...6a07d9853ab7686df7440a47d1b585c6c9f3be35 ``` $ git log --oneline 41c0106..6a07d98 6a07d98 Merge pull request #93 from JuliaLang/ib/guard_rmprocs 41cd14f suppress interrupt trace from SIGTERM test 2b23ae4 guard rmprocs in tests 8c03305 do not call worker_from_id with pid<1 (#92) 25ee836 Add warning about new workers not sharing prior global state (#14) ``` Co-authored-by: Dilum Aluthge --- .../md5 | 1 - .../sha512 | 1 - .../md5 | 1 + .../sha512 | 1 + stdlib/Distributed.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 deps/checksums/Distributed-41c01069533e22a6ce6b794746e4b3aa9f5a25cd.tar.gz/md5 delete mode 100644 deps/checksums/Distributed-41c01069533e22a6ce6b794746e4b3aa9f5a25cd.tar.gz/sha512 create mode 100644 deps/checksums/Distributed-6a07d9853ab7686df7440a47d1b585c6c9f3be35.tar.gz/md5 create mode 100644 deps/checksums/Distributed-6a07d9853ab7686df7440a47d1b585c6c9f3be35.tar.gz/sha512 diff --git a/deps/checksums/Distributed-41c01069533e22a6ce6b794746e4b3aa9f5a25cd.tar.gz/md5 b/deps/checksums/Distributed-41c01069533e22a6ce6b794746e4b3aa9f5a25cd.tar.gz/md5 deleted file mode 100644 index 91dfaf6968e2b..0000000000000 --- a/deps/checksums/Distributed-41c01069533e22a6ce6b794746e4b3aa9f5a25cd.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -5c6463034c358a254074e86ab81720b1 diff --git a/deps/checksums/Distributed-41c01069533e22a6ce6b794746e4b3aa9f5a25cd.tar.gz/sha512 b/deps/checksums/Distributed-41c01069533e22a6ce6b794746e4b3aa9f5a25cd.tar.gz/sha512 deleted file mode 100644 index 0ad09e2e6bf50..0000000000000 --- a/deps/checksums/Distributed-41c01069533e22a6ce6b794746e4b3aa9f5a25cd.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -bebc472ed89afc8f48eabe0ec0673cf416c5fc3b2f3c51599b388f47e47e6c9905a8a033a3f4b5c38a29be515c43fd70ef44750e7d6f8c6ecd8dc491b3012ac0 diff --git a/deps/checksums/Distributed-6a07d9853ab7686df7440a47d1b585c6c9f3be35.tar.gz/md5 b/deps/checksums/Distributed-6a07d9853ab7686df7440a47d1b585c6c9f3be35.tar.gz/md5 new file mode 100644 index 0000000000000..f6ae9d2d77aeb --- /dev/null +++ b/deps/checksums/Distributed-6a07d9853ab7686df7440a47d1b585c6c9f3be35.tar.gz/md5 @@ -0,0 +1 @@ +316bc519c49cd54685cfceb76a4dab5d diff --git a/deps/checksums/Distributed-6a07d9853ab7686df7440a47d1b585c6c9f3be35.tar.gz/sha512 b/deps/checksums/Distributed-6a07d9853ab7686df7440a47d1b585c6c9f3be35.tar.gz/sha512 new file mode 100644 index 0000000000000..275997e84e6d5 --- /dev/null +++ b/deps/checksums/Distributed-6a07d9853ab7686df7440a47d1b585c6c9f3be35.tar.gz/sha512 @@ -0,0 +1 @@ +e71c269c5ca92f4b5b709b871dd1bb06f9e23c5b1444a30f780ccb37f4aa19b50668a5f81c85269f7cea5ebe740b453c1b3fe1569629f441d01d8964cd185e54 diff --git a/stdlib/Distributed.version b/stdlib/Distributed.version index ca528066e9403..b0acacf2367de 100644 --- a/stdlib/Distributed.version +++ b/stdlib/Distributed.version @@ -1,4 +1,4 @@ DISTRIBUTED_BRANCH = master -DISTRIBUTED_SHA1 = 41c01069533e22a6ce6b794746e4b3aa9f5a25cd +DISTRIBUTED_SHA1 = 6a07d9853ab7686df7440a47d1b585c6c9f3be35 DISTRIBUTED_GIT_URL := https://github.com/JuliaLang/Distributed.jl DISTRIBUTED_TAR_URL = https://api.github.com/repos/JuliaLang/Distributed.jl/tarball/$1 From 7f9288098b0140e4738e770e9de7dcb51d5dce3d Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 26 Feb 2024 16:06:35 -0500 Subject: [PATCH 11/13] add dedicated IO thread (capability only) (#53422) It has been oft-requested that we have a dedicated IO thread. That actually turns out to already be the case of something that exists, except that we hard-code the identity of that thread as being thread 0. This PR replaces all of the places where we hard code that assumption with a variable so that they are more easily searched for in the code. It also adds an internal function (`jl_set_io_loop_tid`) that can be used to transfer ownership of the loop to any (valid) tid. In conjunction with the prior foreign-threads work and foreign-thread pool, this lets us spawn a dedicate IO-management thread with this bit of code: ```julia function make_io_thread() tid = UInt[0] threadwork = @cfunction function(arg::Ptr{Cvoid}) Base.errormonitor(current_task()) # this may not go particularly well if the IO loop is dead, but try anyways @ccall jl_set_io_loop_tid((Threads.threadid() - 1)::Int16)::Cvoid wait() # spin uv_run as long as needed nothing end Cvoid (Ptr{Cvoid},) err = @ccall uv_thread_create(tid::Ptr{UInt}, threadwork::Ptr{Cvoid}, C_NULL::Ptr{Cvoid})::Cint err == 0 || Base.uv_error("uv_thread_create", err) @ccall uv_thread_detach(tid::Ptr{UInt})::Cint err == 0 || Base.uv_error("uv_thread_detach", err) # n.b. this does not wait for the thread to start or to take ownership of the event loop nothing end ``` --- base/stream.jl | 1 + src/jl_uv.c | 8 +++----- src/julia_internal.h | 23 ++--------------------- src/scheduler.c | 14 ++++++-------- src/threading.c | 25 +++++++++++++++++++++++-- 5 files changed, 35 insertions(+), 36 deletions(-) diff --git a/base/stream.jl b/base/stream.jl index 3264b8f153677..feb5ad777fc11 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -619,6 +619,7 @@ function notify_filled(buffer::IOBuffer, nread::Int) buffer.size += nread else buffer.ptr += nread + buffer.size = max(buffer.size, buffer.ptr - 1) end nothing end diff --git a/src/jl_uv.c b/src/jl_uv.c index e447faf8fa9c2..4da23a5937770 100644 --- a/src/jl_uv.c +++ b/src/jl_uv.c @@ -373,8 +373,6 @@ JL_DLLEXPORT void *jl_uv_handle_data(uv_handle_t *handle) { return handle->data; */ JL_DLLEXPORT void *jl_uv_write_handle(uv_write_t *req) { return req->handle; } -extern _Atomic(unsigned) _threadedregion; - /** * @brief Process pending UV events. * @@ -387,7 +385,7 @@ JL_DLLEXPORT int jl_process_events(void) jl_task_t *ct = jl_current_task; uv_loop_t *loop = jl_io_loop; jl_gc_safepoint_(ct->ptls); - if (loop && (jl_atomic_load_relaxed(&_threadedregion) || jl_atomic_load_relaxed(&ct->tid) == 0)) { + if (loop && (jl_atomic_load_relaxed(&_threadedregion) || jl_atomic_load_relaxed(&ct->tid) == jl_atomic_load_relaxed(&io_loop_tid))) { if (jl_atomic_load_relaxed(&jl_uv_n_waiters) == 0 && jl_mutex_trylock(&jl_uv_mutex)) { JL_PROBE_RT_START_PROCESS_EVENTS(ct); loop->stop_flag = 0; @@ -637,7 +635,7 @@ JL_DLLEXPORT int jl_fs_write(uv_os_fd_t handle, const char *data, size_t len, { jl_task_t *ct = jl_get_current_task(); // TODO: fix this cheating - if (jl_get_safe_restore() || ct == NULL || jl_atomic_load_relaxed(&ct->tid) != 0) + if (jl_get_safe_restore() || ct == NULL || jl_atomic_load_relaxed(&ct->tid) != jl_atomic_load_relaxed(&io_loop_tid)) #ifdef _OS_WINDOWS_ return WriteFile(handle, data, len, NULL, NULL); #else @@ -718,7 +716,7 @@ JL_DLLEXPORT void jl_uv_puts(uv_stream_t *stream, const char *str, size_t n) // TODO: Hack to make CoreIO thread-safer jl_task_t *ct = jl_get_current_task(); - if (ct == NULL || jl_atomic_load_relaxed(&ct->tid) != 0) { + if (ct == NULL || jl_atomic_load_relaxed(&ct->tid) != jl_atomic_load_relaxed(&io_loop_tid)) { if (stream == JL_STDOUT) { fd = UV_STDOUT_FD; } diff --git a/src/julia_internal.h b/src/julia_internal.h index bb98001fcb6e3..b9f4268f77d3f 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -97,23 +97,6 @@ JL_DLLIMPORT void *__tsan_get_current_fiber(void); JL_DLLIMPORT void __tsan_destroy_fiber(void *fiber); JL_DLLIMPORT void __tsan_switch_to_fiber(void *fiber, unsigned flags); #endif -#ifdef __cplusplus -} -#endif - -// Remove when C11 is required for C code. -#ifndef static_assert -# ifndef __cplusplus -// C11 should already have `static_assert` from `` so there's no need -// to check C version. -# ifdef __GNUC__ -# define static_assert _Static_assert -# else -# define static_assert(...) -# endif -# endif -// For C++, C++11 or MSVC is required. Both provide `static_assert`. -#endif #ifndef alignof # ifndef __cplusplus @@ -182,10 +165,8 @@ extern jl_mutex_t jl_uv_mutex; extern _Atomic(int) jl_uv_n_waiters; void JL_UV_LOCK(void); #define JL_UV_UNLOCK() JL_UNLOCK(&jl_uv_mutex) - -#ifdef __cplusplus -extern "C" { -#endif +extern _Atomic(unsigned) _threadedregion; +extern _Atomic(uint16_t) io_loop_tid; int jl_running_under_rr(int recheck) JL_NOTSAFEPOINT; diff --git a/src/scheduler.c b/src/scheduler.c index dbc913353ce4c..81cf03bc38c5b 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -417,8 +417,6 @@ static int may_sleep(jl_ptls_t ptls) JL_NOTSAFEPOINT } -extern _Atomic(unsigned) _threadedregion; - JL_DLLEXPORT jl_task_t *jl_task_get_next(jl_value_t *trypoptask, jl_value_t *q, jl_value_t *checkempty) { jl_task_t *ct = jl_current_task; @@ -438,7 +436,7 @@ JL_DLLEXPORT jl_task_t *jl_task_get_next(jl_value_t *trypoptask, jl_value_t *q, jl_cpu_pause(); jl_ptls_t ptls = ct->ptls; - if (sleep_check_after_threshold(&start_cycles) || (ptls->tid == 0 && (!jl_atomic_load_relaxed(&_threadedregion) || wait_empty))) { + if (sleep_check_after_threshold(&start_cycles) || (ptls->tid == jl_atomic_load_relaxed(&io_loop_tid) && (!jl_atomic_load_relaxed(&_threadedregion) || wait_empty))) { // acquire sleep-check lock jl_atomic_store_relaxed(&ptls->sleep_check_state, sleeping); jl_fence(); // [^store_buffering_1] @@ -485,7 +483,7 @@ JL_DLLEXPORT jl_task_t *jl_task_get_next(jl_value_t *trypoptask, jl_value_t *q, if (jl_atomic_load_relaxed(&_threadedregion)) { uvlock = jl_mutex_trylock(&jl_uv_mutex); } - else if (ptls->tid == 0) { + else if (ptls->tid == jl_atomic_load_relaxed(&io_loop_tid)) { uvlock = 1; JL_UV_LOCK(); } @@ -526,7 +524,7 @@ JL_DLLEXPORT jl_task_t *jl_task_get_next(jl_value_t *trypoptask, jl_value_t *q, start_cycles = 0; continue; } - if (!enter_eventloop && !jl_atomic_load_relaxed(&_threadedregion) && ptls->tid == 0) { + if (!enter_eventloop && !jl_atomic_load_relaxed(&_threadedregion) && ptls->tid == jl_atomic_load_relaxed(&io_loop_tid)) { // thread 0 is the only thread permitted to run the event loop // so it needs to stay alive, just spin-looping if necessary if (set_not_sleeping(ptls)) { @@ -543,10 +541,10 @@ JL_DLLEXPORT jl_task_t *jl_task_get_next(jl_value_t *trypoptask, jl_value_t *q, assert(wasrunning); if (wasrunning == 1) { // This was the last running thread, and there is no thread with !may_sleep - // so make sure tid 0 is notified to check wait_empty + // so make sure io_loop_tid is notified to check wait_empty // TODO: this also might be a good time to check again that // libuv's queue is truly empty, instead of during delete_thread - if (ptls->tid != 0) { + if (ptls->tid != jl_atomic_load_relaxed(&io_loop_tid)) { uv_mutex_lock(&ptls->sleep_lock); uv_cond_wait(&ptls->wake_signal, &ptls->sleep_lock); uv_mutex_unlock(&ptls->sleep_lock); @@ -597,7 +595,7 @@ void scheduler_delete_thread(jl_ptls_t ptls) JL_NOTSAFEPOINT jl_fence(); if (notsleeping) { if (jl_atomic_load_relaxed(&nrunning) == 1) { - jl_ptls_t ptls2 = jl_atomic_load_relaxed(&jl_all_tls_states)[0]; + jl_ptls_t ptls2 = jl_atomic_load_relaxed(&jl_all_tls_states)[jl_atomic_load_relaxed(&io_loop_tid)]; // This was the last running thread, and there is no thread with !may_sleep // so make sure tid 0 is notified to check wait_empty uv_mutex_lock(&ptls2->sleep_lock); diff --git a/src/threading.c b/src/threading.c index 2eecb59db1f17..8879a34d6b701 100644 --- a/src/threading.c +++ b/src/threading.c @@ -808,7 +808,8 @@ void jl_start_threads(void) uv_barrier_wait(&thread_init_done); } -_Atomic(unsigned) _threadedregion; // HACK: keep track of whether to prioritize IO or threading +_Atomic(unsigned) _threadedregion; // keep track of whether to prioritize IO or threading +_Atomic(uint16_t) io_loop_tid; // mark which thread is assigned to run the uv_loop JL_DLLEXPORT int jl_in_threaded_region(void) { @@ -829,7 +830,27 @@ JL_DLLEXPORT void jl_exit_threaded_region(void) JL_UV_UNLOCK(); // make sure thread 0 is not using the sleep_lock // so that it may enter the libuv event loop instead - jl_wakeup_thread(0); + jl_fence(); + jl_wakeup_thread(jl_atomic_load_relaxed(&io_loop_tid)); + } +} + +JL_DLLEXPORT void jl_set_io_loop_tid(int16_t tid) +{ + if (tid < 0 || tid >= jl_atomic_load_relaxed(&jl_n_threads)) { + // TODO: do we care if this thread has exited or not started yet, + // since ptls2 might not be defined yet and visible on all threads yet + return; + } + jl_atomic_store_relaxed(&io_loop_tid, tid); + jl_fence(); + if (jl_atomic_load_relaxed(&_threadedregion) == 0) { + // make sure the previous io_loop_tid leaves the libuv event loop + JL_UV_LOCK(); + JL_UV_UNLOCK(); + // make sure thread io_loop_tid is not using the sleep_lock + // so that it may enter the libuv event loop instead + jl_wakeup_thread(tid); } } From a2be715dde75cfdc5cc0e5debcf1ce37b693cd8b Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 26 Feb 2024 16:08:57 -0500 Subject: [PATCH 12/13] gf: allow method shadowing with exact signatures without deletion (#53415) We already allowed method shadowing for an inexact signature and implicit method deletion by exact signatures, so it was fairly arbitrary to implement it as a deletion for a replacement by an exact signature rather than use the morespecific definition for this. This change should be useful to Mocking libraries, such as Pluto, which previously had a buggier version of this which tried to re-activate or re-define the old methods. There is a bit of code cleanup in here, either of unused features, or of aspects that were broken, or of world_valid computations that were not actually impacting the final result (e.g. when there is a more specific result matches, it does not need to limit the result valid world range because of a less specific result that does not get returned). --- NEWS.md | 10 ++ base/deprecated.jl | 8 +- base/reflection.jl | 7 +- doc/src/devdocs/types.md | 10 +- doc/src/manual/modules.md | 8 +- src/gf.c | 137 +++++++++++++--------- src/jl_exported_funcs.inc | 2 +- src/julia.h | 1 + src/julia_internal.h | 2 - src/subtype.c | 20 ++++ src/typemap.c | 25 +--- stdlib/Serialization/src/Serialization.jl | 2 +- test/compiler/invalidation.jl | 8 +- test/reflection.jl | 2 +- test/specificity.jl | 4 +- test/worlds.jl | 24 ++++ 16 files changed, 161 insertions(+), 109 deletions(-) diff --git a/NEWS.md b/NEWS.md index c37cb9efdd9b8..56a2ffb8d539d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -7,6 +7,16 @@ New language features Language changes ---------------- + - When methods are replaced with exactly equivalent ones, the old method is no + longer deleted implicitly simultaneously, although the new method does take + priority and become more specific than the old method. Thus if the new + method is deleted later, the old method will resume operating. This can be + useful to mocking frameworks (such as in SparseArrays, Pluto, and Mocking, + among others), as they do not need to explicitly restore the old method. + While inference and compilation still must be repeated with this, it also + may pave the way for inference to be able to intelligently re-use the old + results, once the new method is deleted. ([#53415]) + Compiler/Runtime improvements ----------------------------- diff --git a/base/deprecated.jl b/base/deprecated.jl index 7e7fa5596ca25..5cb054f426344 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -29,11 +29,11 @@ To prevent `old` from being exported, set `export_old` to `false`. # Examples ```jldoctest -julia> @deprecate old(x) new(x) -old (generic function with 1 method) +julia> @deprecate old_export(x) new(x) +old_export (generic function with 1 method) -julia> @deprecate old(x) new(x) false -old (generic function with 1 method) +julia> @deprecate old_public(x) new(x) false +old_public (generic function with 1 method) ``` Calls to `@deprecate` without explicit type-annotations will define diff --git a/base/reflection.jl b/base/reflection.jl index 202573b02f1bf..446e5825a16cc 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -887,6 +887,7 @@ A special case where exact behavior is guaranteed: when `T <: S`, typeintersect(@nospecialize(a), @nospecialize(b)) = (@_total_meta; ccall(:jl_type_intersection, Any, (Any, Any), a::Type, b::Type)) morespecific(@nospecialize(a), @nospecialize(b)) = (@_total_meta; ccall(:jl_type_morespecific, Cint, (Any, Any), a::Type, b::Type) != 0) +morespecific(a::Method, b::Method) = ccall(:jl_method_morespecific, Cint, (Any, Any), a, b) != 0 """ fieldoffset(type, i) @@ -2492,7 +2493,7 @@ function isambiguous(m1::Method, m2::Method; ambiguous_bottom::Bool=false) for match in ms m = match.method match.fully_covers || continue - if minmax === nothing || morespecific(m.sig, minmax.sig) + if minmax === nothing || morespecific(m, minmax) minmax = m end end @@ -2502,8 +2503,8 @@ function isambiguous(m1::Method, m2::Method; ambiguous_bottom::Bool=false) for match in ms m = match.method m === minmax && continue - if !morespecific(minmax.sig, m.sig) - if match.fully_covers || !morespecific(m.sig, minmax.sig) + if !morespecific(minmax, m) + if match.fully_covers || !morespecific(m, minmax) return true end end diff --git a/doc/src/devdocs/types.md b/doc/src/devdocs/types.md index 42bdf251ac82f..120c948c6cadc 100644 --- a/doc/src/devdocs/types.md +++ b/doc/src/devdocs/types.md @@ -521,10 +521,6 @@ than the other.) Likewise, `Tuple{Int,Vararg{Int}}` is not a subtype of `Tuple{ considered more specific. However, `morespecific` does get a bonus for length: in particular, `Tuple{Int,Int}` is more specific than `Tuple{Int,Vararg{Int}}`. -If you're debugging how methods get sorted, it can be convenient to define the function: - -```julia -type_morespecific(a, b) = ccall(:jl_type_morespecific, Cint, (Any,Any), a, b) -``` - -which allows you to test whether tuple type `a` is more specific than tuple type `b`. +Additionally, if 2 methods are defined with identical signatures, per type-equal, then they +will instead by compared by order of addition, such that the later method is more specific +than the earlier one. diff --git a/doc/src/manual/modules.md b/doc/src/manual/modules.md index 8c366616bac49..64befb03c1ad5 100644 --- a/doc/src/manual/modules.md +++ b/doc/src/manual/modules.md @@ -184,7 +184,6 @@ Stacktrace: @ none:0 [2] top-level scope @ none:1 - ``` This error prevents accidentally adding methods to functions in other modules that you only intended to use. @@ -196,17 +195,16 @@ julia> using .NiceStuff julia> struct Cat end julia> NiceStuff.nice(::Cat) = "nice ๐Ÿ˜ธ" - ``` Alternatively, you can `import` the specific function name: ```jldoctest module_manual julia> import .NiceStuff: nice -julia> struct Cat end +julia> struct Mouse end -julia> nice(::Cat) = "nice ๐Ÿ˜ธ" -nice (generic function with 2 methods) +julia> nice(::Mouse) = "nice ๐Ÿญ" +nice (generic function with 3 methods) ``` Which one you choose is a matter of style. The first form makes it clear that you are adding a diff --git a/src/gf.c b/src/gf.c index f6a9d82a4625d..88890b7e5f203 100644 --- a/src/gf.c +++ b/src/gf.c @@ -276,7 +276,7 @@ JL_DLLEXPORT jl_value_t *jl_methtable_lookup(jl_methtable_t *mt, jl_value_t *typ // TODO: this is sort of an odd lookup strategy (and the only user of // jl_typemap_assoc_by_type with subtype=0), while normally jl_gf_invoke_lookup would be // expected to be used instead - struct jl_typemap_assoc search = {type, world, NULL, 0, ~(size_t)0}; + struct jl_typemap_assoc search = {type, world, NULL}; jl_typemap_entry_t *sf = jl_typemap_assoc_by_type(jl_atomic_load_relaxed(&mt->defs), &search, jl_cachearg_offset(mt), /*subtype*/0); if (!sf) return jl_nothing; @@ -299,6 +299,8 @@ jl_datatype_t *jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_a m->module = jl_core_module; m->isva = 1; m->nargs = 2; + jl_atomic_store_relaxed(&m->primary_world, 1); + jl_atomic_store_relaxed(&m->deleted_world, ~(size_t)0); m->sig = (jl_value_t*)jl_anytuple_type; m->slot_syms = jl_an_empty_string; m->nospecialize = 0; @@ -309,7 +311,7 @@ jl_datatype_t *jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_a JL_GC_PUSH2(&m, &newentry); newentry = jl_typemap_alloc(jl_anytuple_type, NULL, jl_emptysvec, - (jl_value_t*)m, 1, ~(size_t)0); + (jl_value_t*)m, jl_atomic_load_relaxed(&m->primary_world), jl_atomic_load_relaxed(&m->deleted_world)); jl_typemap_insert(&mt->defs, (jl_value_t*)mt, newentry, jl_cachearg_offset(mt)); jl_method_instance_t *mi = jl_get_specialized(m, (jl_value_t*)jl_anytuple_type, jl_emptysvec); @@ -1236,7 +1238,7 @@ static jl_method_instance_t *cache_method( if (entry) return entry->func.linfo; } - struct jl_typemap_assoc search = {(jl_value_t*)tt, world, NULL, 0, ~(size_t)0}; + struct jl_typemap_assoc search = {(jl_value_t*)tt, world, NULL}; jl_typemap_entry_t *entry = jl_typemap_assoc_by_type(jl_atomic_load_relaxed(cache), &search, offs, /*subtype*/1); if (entry && entry->func.value) return entry->func.linfo; @@ -1387,7 +1389,7 @@ static jl_method_instance_t *cache_method( // short-circuit if an existing entry is already present // that satisfies our requirements if (cachett != tt) { - struct jl_typemap_assoc search = {(jl_value_t*)cachett, world, NULL, 0, ~(size_t)0}; + struct jl_typemap_assoc search = {(jl_value_t*)cachett, world, NULL}; jl_typemap_entry_t *entry = jl_typemap_assoc_by_type(jl_atomic_load_relaxed(cache), &search, offs, /*subtype*/1); if (entry && jl_egal((jl_value_t*)entry->simplesig, simplett ? (jl_value_t*)simplett : jl_nothing) && jl_egal((jl_value_t*)guardsigs, (jl_value_t*)entry->guardsigs)) { @@ -1451,7 +1453,7 @@ static jl_method_instance_t *jl_mt_assoc_by_type(jl_methtable_t *mt JL_PROPAGATE } if (!mi) { - struct jl_typemap_assoc search = {(jl_value_t*)tt, world, NULL, 0, ~(size_t)0}; + struct jl_typemap_assoc search = {(jl_value_t*)tt, world, NULL}; jl_typemap_entry_t *entry = jl_typemap_assoc_by_type(jl_atomic_load_relaxed(&mt->cache), &search, jl_cachearg_offset(mt), /*subtype*/1); if (entry) mi = entry->func.linfo; @@ -1491,7 +1493,8 @@ static int get_intersect_visitor(jl_typemap_entry_t *oldentry, struct typemap_in jl_method_t *oldmethod = oldentry->func.method; if (closure->match.issubty // e.g. jl_subtype(closure->newentry.sig, oldentry->sig) && jl_subtype(oldmethod->sig, (jl_value_t*)closure->newentry->sig)) { // e.g. jl_type_equal(closure->newentry->sig, oldentry->sig) - closure->replaced = oldentry; + if (closure->replaced == NULL || jl_atomic_load_relaxed(&closure->replaced->min_world) < jl_atomic_load_relaxed(&oldentry->min_world)) + closure->replaced = oldentry; // must pick the newest insertion (both are still valid) } if (closure->shadowed == NULL) closure->shadowed = (jl_value_t*)jl_alloc_vec_any(0); @@ -1795,13 +1798,18 @@ static int invalidate_mt_cache(jl_typemap_entry_t *oldentry, void *closure0) } return 1; } + +struct disable_mt_env { + jl_method_t *replaced; + size_t max_world; +}; static int disable_mt_cache(jl_typemap_entry_t *oldentry, void *closure0) { - struct invalidate_mt_env *env = (struct invalidate_mt_env*)closure0; + struct disable_mt_env *env = (struct disable_mt_env*)closure0; if (jl_atomic_load_relaxed(&oldentry->max_world) < ~(size_t)0) return 1; jl_method_t *m = oldentry->func.linfo->def.method; - if (m == env->newentry->func.method) + if (m == env->replaced) jl_atomic_store_relaxed(&oldentry->max_world, env->max_world); return 1; } @@ -1815,33 +1823,23 @@ static int typemap_search(jl_typemap_entry_t *entry, void *closure) return 1; } -static jl_typemap_entry_t *do_typemap_search(jl_methtable_t *mt JL_PROPAGATES_ROOT, jl_method_t *method) JL_NOTSAFEPOINT; - -#ifndef __clang_gcanalyzer__ /* in general, jl_typemap_visitor could be a safepoint, but not for typemap_search */ -static jl_typemap_entry_t *do_typemap_search(jl_methtable_t *mt JL_PROPAGATES_ROOT, jl_method_t *method) JL_NOTSAFEPOINT { +static jl_typemap_entry_t *do_typemap_search(jl_methtable_t *mt JL_PROPAGATES_ROOT, jl_method_t *method) { jl_value_t *closure = (jl_value_t*)(method); if (jl_typemap_visitor(jl_atomic_load_relaxed(&mt->defs), typemap_search, &closure)) jl_error("method not in method table"); return (jl_typemap_entry_t *)closure; } -#endif -static void jl_method_table_invalidate(jl_methtable_t *mt, jl_typemap_entry_t *methodentry, size_t max_world) +static void jl_method_table_invalidate(jl_methtable_t *mt, jl_method_t *replaced, size_t max_world) { if (jl_options.incremental && jl_generating_output()) jl_error("Method deletion is not possible during Module precompile."); - jl_method_t *method = methodentry->func.method; - assert(!method->is_for_opaque_closure); + assert(!replaced->is_for_opaque_closure); assert(jl_atomic_load_relaxed(&jl_world_counter) == max_world); - assert(jl_atomic_load_relaxed(&method->deleted_world) == ~(size_t)0); - jl_atomic_store_relaxed(&method->deleted_world, max_world); - jl_atomic_store_relaxed(&methodentry->max_world, max_world); // drop this method from mt->cache - struct invalidate_mt_env mt_cache_env; + struct disable_mt_env mt_cache_env; mt_cache_env.max_world = max_world; - mt_cache_env.newentry = methodentry; - mt_cache_env.shadowed = NULL; - mt_cache_env.invalidated = 0; + mt_cache_env.replaced = replaced; jl_typemap_visitor(jl_atomic_load_relaxed(&mt->cache), disable_mt_cache, (void*)&mt_cache_env); jl_genericmemory_t *leafcache = jl_atomic_load_relaxed(&mt->leafcache); size_t i, l = leafcache->length; @@ -1849,15 +1847,14 @@ static void jl_method_table_invalidate(jl_methtable_t *mt, jl_typemap_entry_t *m jl_typemap_entry_t *oldentry = (jl_typemap_entry_t*)jl_genericmemory_ptr_ref(leafcache, i); if (oldentry) { while ((jl_value_t*)oldentry != jl_nothing) { - if (jl_atomic_load_relaxed(&oldentry->max_world) == ~(size_t)0) - jl_atomic_store_relaxed(&oldentry->max_world, mt_cache_env.max_world); + disable_mt_cache(oldentry, (void*)&mt_cache_env); oldentry = jl_atomic_load_relaxed(&oldentry->next); } } } // Invalidate the backedges int invalidated = 0; - jl_value_t *specializations = jl_atomic_load_relaxed(&method->specializations); + jl_value_t *specializations = jl_atomic_load_relaxed(&replaced->specializations); JL_GC_PUSH1(&specializations); if (!jl_is_svec(specializations)) specializations = (jl_value_t*)jl_svec1(specializations); @@ -1873,7 +1870,7 @@ static void jl_method_table_invalidate(jl_methtable_t *mt, jl_typemap_entry_t *m // XXX: this might have resolved an ambiguity, for which we have not tracked the edge here, // and thus now introduce a mistake into inference if (invalidated && _jl_debug_method_invalidation) { - jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)method); + jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)replaced); jl_value_t *loctag = jl_cstr_to_string("jl_method_table_disable"); JL_GC_PUSH1(&loctag); jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag); @@ -1888,7 +1885,11 @@ JL_DLLEXPORT void jl_method_table_disable(jl_methtable_t *mt, jl_method_t *metho JL_LOCK(&mt->writelock); // Narrow the world age on the method to make it uncallable size_t world = jl_atomic_load_relaxed(&jl_world_counter); - jl_method_table_invalidate(mt, methodentry, world); + assert(method == methodentry->func.method); + assert(jl_atomic_load_relaxed(&method->deleted_world) == ~(size_t)0); + jl_atomic_store_relaxed(&method->deleted_world, world); + jl_atomic_store_relaxed(&methodentry->max_world, world); + jl_method_table_invalidate(mt, method, world); jl_atomic_store_release(&jl_world_counter, world + 1); JL_UNLOCK(&mt->writelock); JL_UNLOCK(&world_counter_lock); @@ -2006,7 +2007,8 @@ void jl_method_table_activate(jl_methtable_t *mt, jl_typemap_entry_t *newentry) oldvalue = (jl_value_t*)replaced; invalidated = 1; method_overwrite(newentry, replaced->func.method); - jl_method_table_invalidate(mt, replaced, max_world); + // this is an optimized version of below, given we know the type-intersection is exact + jl_method_table_invalidate(mt, replaced->func.method, max_world); } else { jl_method_t *const *d; @@ -2817,7 +2819,7 @@ static jl_method_instance_t *jl_get_compile_hint_specialization(jl_tupletype_t * exclude = 0; for (size_t j = n-1; j > i; j--) { // more general methods maybe more likely to be at end jl_method_match_t *match2 = (jl_method_match_t*)jl_array_ptr_ref(matches, j); - if (jl_type_morespecific(match1->method->sig, match2->method->sig)) { + if (jl_method_morespecific(match1->method, match2->method)) { exclude = 1; break; } @@ -3348,18 +3350,23 @@ static int ml_matches_visitor(jl_typemap_entry_t *ml, struct typemap_intersectio closure->match.min_valid = max_world + 1; return 1; } - else { - // intersect the env valid range with method's inclusive valid range - if (closure->match.min_valid < min_world) - closure->match.min_valid = min_world; - if (closure->match.max_valid > max_world) - closure->match.max_valid = max_world; - } jl_method_t *meth = ml->func.method; if (closure->lim >= 0 && jl_is_dispatch_tupletype(meth->sig)) { - if (closure->lim == 0) - return 0; - closure->lim--; + int replaced = 0; + // check if this is replaced, in which case we need to avoid double-counting it against the limit + // (although it will figure out later which one to keep and return) + size_t len = jl_array_nrows(closure->t); + for (int i = 0; i < len; i++) { + if (jl_types_equal(((jl_method_match_t*)jl_array_ptr_ref(closure->t, i))->method->sig, meth->sig)) { + replaced = 1; + break; + } + } + if (!replaced) { + if (closure->lim == 0) + return 0; + closure->lim--; + } } // don't need to consider other similar methods if this ml will always fully intersect with them and dominates all of them if (!closure->include_ambiguous || closure->lim != -1) @@ -3384,7 +3391,6 @@ static int ml_mtable_visitor(jl_methtable_t *mt, void *closure0) return jl_typemap_intersection_visitor(jl_atomic_load_relaxed(&mt->defs), jl_cachearg_offset(mt), env); } - // Visit the candidate methods, starting from t[idx], to determine a possible valid sort ordering, // where every morespecific method appears before any method which it has a common // intersection with but is not partly ambiguous with (ambiguity is transitive, particularly @@ -3435,7 +3441,7 @@ static int sort_mlmatches(jl_array_t *t, size_t idx, arraylist_t *visited, array jl_method_t *m2 = matc2->method; if (jl_subtype(ti, m2->sig)) { if (include_ambiguous) { - if (!jl_type_morespecific((jl_value_t*)m2->sig, (jl_value_t*)m->sig)) + if (!jl_method_morespecific(m2, m)) continue; } visited->items[idx] = (void*)1; @@ -3469,8 +3475,8 @@ static int sort_mlmatches(jl_array_t *t, size_t idx, arraylist_t *visited, array // since we only care about sorting of the intersections the user asked us about if (!subt2 && jl_has_empty_intersection(m2->sig, m->sig)) continue; - int msp = jl_type_morespecific((jl_value_t*)m->sig, (jl_value_t*)m2->sig); - int msp2 = !msp && jl_type_morespecific((jl_value_t*)m2->sig, (jl_value_t*)m->sig); + int msp = jl_method_morespecific(m, m2); + int msp2 = !msp && jl_method_morespecific(m2, m); if (!msp) { if (subt || !include_ambiguous || (lim != -1 && msp2)) { if (subt2 || jl_subtype((jl_value_t*)ti, m2->sig)) { @@ -3510,7 +3516,7 @@ static int sort_mlmatches(jl_array_t *t, size_t idx, arraylist_t *visited, array jl_method_t *m2 = matc2->method; if (jl_subtype(ti, m2->sig)) { if (include_ambiguous) { - if (!jl_type_morespecific((jl_value_t*)m2->sig, (jl_value_t*)m->sig)) + if (!jl_method_morespecific(m2, m)) continue; } visited->items[idx] = (void*)1; @@ -3586,7 +3592,7 @@ static int sort_mlmatches(jl_array_t *t, size_t idx, arraylist_t *visited, array jl_method_t *m2 = matc2->method; if (jl_subtype(ti, m2->sig)) { if (include_ambiguous) { - if (!jl_type_morespecific((jl_value_t*)m2->sig, (jl_value_t*)m->sig)) + if (!jl_method_morespecific(m2, m)) continue; } visited->items[childidx] = (void*)1; @@ -3617,8 +3623,7 @@ static int sort_mlmatches(jl_array_t *t, size_t idx, arraylist_t *visited, array // we don't consider that a third method might be // disrupting that ordering and just consider them // pairwise to keep this simple). - if (!jl_type_morespecific((jl_value_t*)m->sig, (jl_value_t*)m2->sig) && - !jl_type_morespecific((jl_value_t*)m2->sig, (jl_value_t*)m->sig)) { + if (!jl_method_morespecific(m, m2) && !jl_method_morespecific(m2, m)) { visited->items[childidx] = (void*)-1; break; } @@ -3656,7 +3661,6 @@ static int sort_mlmatches(jl_array_t *t, size_t idx, arraylist_t *visited, array } - // This is the collect form of calling jl_typemap_intersection_visitor // with optimizations to skip fully shadowed methods. // @@ -3692,7 +3696,7 @@ static jl_value_t *ml_matches(jl_methtable_t *mt, /* .ti = */ NULL, /* .env = */ jl_emptysvec, /* .issubty = */ 0}, intersections, world, lim, include_ambiguous, /* .t = */ jl_an_empty_vec_any, /* .matc = */ NULL}; - struct jl_typemap_assoc search = {(jl_value_t*)type, world, jl_emptysvec, 1, ~(size_t)0}; + struct jl_typemap_assoc search = {(jl_value_t*)type, world, jl_emptysvec}; jl_value_t *isect2 = NULL; JL_GC_PUSH6(&env.t, &env.matc, &env.match.env, &search.env, &env.match.ti, &isect2); @@ -3760,6 +3764,9 @@ static jl_value_t *ml_matches(jl_methtable_t *mt, } if (!ml_mtable_visitor(mt, &env.match)) { JL_GC_POP(); + // if we return early, set only the min/max valid collected from matching + *min_valid = env.match.min_valid; + *max_valid = env.match.max_valid; return jl_nothing; } } @@ -3767,9 +3774,13 @@ static jl_value_t *ml_matches(jl_methtable_t *mt, // else: scan everything if (!jl_foreach_reachable_mtable(ml_mtable_visitor, &env.match)) { JL_GC_POP(); + // if we return early, set only the min/max valid collected from matching + *min_valid = env.match.min_valid; + *max_valid = env.match.max_valid; return jl_nothing; } } + // if we return early, set only the min/max valid collected from matching *min_valid = env.match.min_valid; *max_valid = env.match.max_valid; // done with many of these values now @@ -3789,7 +3800,7 @@ static jl_value_t *ml_matches(jl_methtable_t *mt, jl_method_t *m = matc->method; if (minmax != NULL) { jl_method_t *minmaxm = minmax->method; - if (jl_type_morespecific((jl_value_t*)minmaxm->sig, (jl_value_t*)m->sig)) + if (jl_method_morespecific(minmaxm, m)) continue; } minmax = matc; @@ -3807,7 +3818,7 @@ static jl_value_t *ml_matches(jl_methtable_t *mt, if (matc->fully_covers == FULLY_COVERS) { jl_method_t *m = matc->method; jl_method_t *minmaxm = minmax->method; - if (!jl_type_morespecific((jl_value_t*)minmaxm->sig, (jl_value_t*)m->sig)) { + if (!jl_method_morespecific(minmaxm, m)) { minmax_ambig = 1; minmax = NULL; has_ambiguity = 1; @@ -3832,7 +3843,7 @@ static jl_value_t *ml_matches(jl_methtable_t *mt, jl_method_match_t *matc = (jl_method_match_t*)jl_array_ptr_ref(env.t, i); if (matc->fully_covers != FULLY_COVERS) { jl_method_t *m = matc->method; - if (jl_type_morespecific((jl_value_t*)minmaxm->sig, (jl_value_t*)m->sig)) + if (jl_method_morespecific(minmaxm, m)) matc->fully_covers = SENTINEL; // put a sentinel value here for sorting else all_subtypes = 0; @@ -3951,8 +3962,7 @@ static jl_value_t *ml_matches(jl_methtable_t *mt, if (ti == jl_bottom_type) continue; // and they aren't themselves simply ordered - if (jl_type_morespecific((jl_value_t*)m->sig, (jl_value_t*)m2->sig) || - jl_type_morespecific((jl_value_t*)m2->sig, (jl_value_t*)m->sig)) + if (jl_method_morespecific(m, m2) || jl_method_morespecific(m2, m)) continue; // now look for a third method m3 that dominated these and that fully covered this intersection already size_t k; @@ -3965,8 +3975,7 @@ static jl_value_t *ml_matches(jl_methtable_t *mt, jl_method_match_t *matc3 = (jl_method_match_t*)jl_array_ptr_ref(env.t, idx3); jl_method_t *m3 = matc3->method; if ((jl_subtype(ti, m3->sig) || (isect2 && jl_subtype(isect2, m3->sig))) - && jl_type_morespecific((jl_value_t*)m3->sig, (jl_value_t*)m->sig) - && jl_type_morespecific((jl_value_t*)m3->sig, (jl_value_t*)m2->sig)) { + && jl_method_morespecific(m3, m) && jl_method_morespecific(m3, m2)) { //if (jl_subtype(matc->spec_types, ti) || jl_subtype(matc->spec_types, matc3->m3->sig)) // // check if it covered not only this intersection, but all intersections with matc // // if so, we do not need to check all of them separately @@ -4008,6 +4017,18 @@ static jl_value_t *ml_matches(jl_methtable_t *mt, jl_array_del_end((jl_array_t*)env.t, len - j); len = j; } + for (j = 0; j < len; j++) { + jl_method_match_t *matc = (jl_method_match_t*)jl_array_ptr_ref(env.t, j); + jl_method_t *m = matc->method; + // method applicability is the same as typemapentry applicability + size_t min_world = jl_atomic_load_relaxed(&m->primary_world); + size_t max_world = jl_atomic_load_relaxed(&m->deleted_world); + // intersect the env valid range with method lookup's inclusive valid range + if (env.match.min_valid < min_world) + env.match.min_valid = min_world; + if (env.match.max_valid > max_world) + env.match.max_valid = max_world; + } if (mt && cache_result && ((jl_datatype_t*)unw)->isdispatchtuple) { // cache_result parameter keeps this from being recursive if (len == 1 && !has_ambiguity) { env.matc = (jl_method_match_t*)jl_array_ptr_ref(env.t, 0); @@ -4018,6 +4039,8 @@ static jl_value_t *ml_matches(jl_methtable_t *mt, JL_UNLOCK(&mt->writelock); } } + *min_valid = env.match.min_valid; + *max_valid = env.match.max_valid; if (ambig != NULL) *ambig = has_ambiguity; JL_GC_POP(); diff --git a/src/jl_exported_funcs.inc b/src/jl_exported_funcs.inc index 4498f3132d1bc..48bbec09688b7 100644 --- a/src/jl_exported_funcs.inc +++ b/src/jl_exported_funcs.inc @@ -479,7 +479,7 @@ XX(jl_type_intersection) \ XX(jl_type_intersection_with_env) \ XX(jl_type_morespecific) \ - XX(jl_type_morespecific_no_subtype) \ + XX(jl_method_morespecific) \ XX(jl_type_union) \ XX(jl_type_unionall) \ XX(jl_unbox_bool) \ diff --git a/src/julia.h b/src/julia.h index 0505b1e88d4bb..a7e0c1b2db17b 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1711,6 +1711,7 @@ JL_DLLEXPORT jl_value_t *jl_type_unionall(jl_tvar_t *v, jl_value_t *body); JL_DLLEXPORT const char *jl_typename_str(jl_value_t *v) JL_NOTSAFEPOINT; JL_DLLEXPORT const char *jl_typeof_str(jl_value_t *v) JL_NOTSAFEPOINT; JL_DLLEXPORT int jl_type_morespecific(jl_value_t *a, jl_value_t *b); +JL_DLLEXPORT int jl_method_morespecific(jl_method_t *ma, jl_method_t *mb); STATIC_INLINE int jl_is_dispatch_tupletype(jl_value_t *v) JL_NOTSAFEPOINT { diff --git a/src/julia_internal.h b/src/julia_internal.h index b9f4268f77d3f..76556e288f387 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -1465,8 +1465,6 @@ struct jl_typemap_assoc { size_t const world; // outputs jl_svec_t *env; // subtype env (initialize to null to perform intersection without an environment) - size_t min_valid; - size_t max_valid; }; jl_typemap_entry_t *jl_typemap_assoc_by_type( diff --git a/src/subtype.c b/src/subtype.c index 4a797aab9831d..c6b51ec872e75 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -5150,6 +5150,26 @@ JL_DLLEXPORT int jl_type_morespecific_no_subtype(jl_value_t *a, jl_value_t *b) return type_morespecific_(a, b, a, b, 0, NULL); } +// Equivalent to `jl_type_morespecific` of the signatures, except that more recent +// methods are more specific, iff the methods signatures are type-equal +JL_DLLEXPORT int jl_method_morespecific(jl_method_t *ma, jl_method_t *mb) +{ + jl_value_t *a = (jl_value_t*)ma->sig; + jl_value_t *b = (jl_value_t*)mb->sig; + if (obviously_disjoint(a, b, 1)) + return 0; + if (jl_has_free_typevars(a) || jl_has_free_typevars(b)) + return 0; + if (jl_subtype(b, a)) { + if (jl_types_equal(a, b)) + return jl_atomic_load_relaxed(&ma->primary_world) > jl_atomic_load_relaxed(&mb->primary_world); + return 0; + } + if (jl_subtype(a, b)) + return 1; + return type_morespecific_(a, b, a, b, 0, NULL); +} + #ifdef __cplusplus } #endif diff --git a/src/typemap.c b/src/typemap.c index 1f69d5da8af6e..b8b699e101fe5 100644 --- a/src/typemap.c +++ b/src/typemap.c @@ -836,9 +836,7 @@ static jl_typemap_entry_t *jl_typemap_entry_assoc_by_type( size_t n = jl_nparams(unw); int typesisva = n == 0 ? 0 : jl_is_vararg(jl_tparam(unw, n-1)); for (; ml != (void*)jl_nothing; ml = jl_atomic_load_relaxed(&ml->next)) { - if (search->max_valid < jl_atomic_load_relaxed(&ml->min_world)) - continue; - if (search->min_valid > jl_atomic_load_relaxed(&ml->max_world)) + if (search->world < jl_atomic_load_relaxed(&ml->min_world) || search->world > jl_atomic_load_relaxed(&ml->max_world)) continue; size_t lensig = jl_nparams(jl_unwrap_unionall((jl_value_t*)ml->sig)); if (lensig == n || (ml->va && lensig <= n+1)) { @@ -877,26 +875,7 @@ static jl_typemap_entry_t *jl_typemap_entry_assoc_by_type( } } if (ismatch) { - size_t min_world = jl_atomic_load_relaxed(&ml->min_world); - size_t max_world = jl_atomic_load_relaxed(&ml->max_world); - if (search->world < min_world) { - // ignore method table entries that are part of a later world - if (search->max_valid >= min_world) - search->max_valid = min_world - 1; - } - else if (search->world > max_world) { - // ignore method table entries that have been replaced in the current world - if (search->min_valid <= max_world) - search->min_valid = max_world + 1; - } - else { - // intersect the env valid range with method's valid range - if (search->min_valid < min_world) - search->min_valid = min_world; - if (search->max_valid > max_world) - search->max_valid = max_world; - return ml; - } + return ml; } } if (resetenv) diff --git a/stdlib/Serialization/src/Serialization.jl b/stdlib/Serialization/src/Serialization.jl index 2e1d4cd801fd9..29010a52eed91 100644 --- a/stdlib/Serialization/src/Serialization.jl +++ b/stdlib/Serialization/src/Serialization.jl @@ -1111,7 +1111,7 @@ function deserialize(s::AbstractSerializer, ::Type{Method}) end if !is_for_opaque_closure mt = ccall(:jl_method_table_for, Any, (Any,), sig) - if mt !== nothing && nothing === ccall(:jl_methtable_lookup, Any, (Any, Any, UInt), mt, sig, typemax(UInt)) + if mt !== nothing && nothing === ccall(:jl_methtable_lookup, Any, (Any, Any, UInt), mt, sig, Base.get_world_counter()) ccall(:jl_method_table_insert, Cvoid, (Any, Any, Ptr{Cvoid}), mt, meth, C_NULL) end end diff --git a/test/compiler/invalidation.jl b/test/compiler/invalidation.jl index d5e86ca533f05..76cf3cbdc0796 100644 --- a/test/compiler/invalidation.jl +++ b/test/compiler/invalidation.jl @@ -142,7 +142,9 @@ begin take!(GLOBAL_BUFFER) # this redefinition below should invalidate the cache of `pr48932_callee` but not that of `pr48932_caller` pr48932_callee(x) = (print(GLOBAL_BUFFER, x); nothing) - @test isempty(Base.specializations(Base.only(Base.methods(pr48932_callee)))) + @test length(Base.methods(pr48932_callee)) == 2 + @test Base.only(Base.methods(pr48932_callee, Tuple{Any})) === first(Base.methods(pr48932_callee)) + @test isempty(Base.specializations(Base.only(Base.methods(pr48932_callee, Tuple{Any})))) let mi = only(Base.specializations(Base.only(Base.methods(pr48932_caller)))) # Base.method_instance(pr48932_callee, (Any,)) ci = mi.cache @@ -206,7 +208,7 @@ begin take!(GLOBAL_BUFFER) # this redefinition below should invalidate the cache of `pr48932_callee_inferable` but not that of `pr48932_caller_unuse` pr48932_callee_inferable(x) = (print(GLOBAL_BUFFER, "foo"); x) - @test isempty(Base.specializations(Base.only(Base.methods(pr48932_callee_inferable)))) + @test isempty(Base.specializations(Base.only(Base.methods(pr48932_callee_inferable, Tuple{Any})))) let mi = Base.method_instance(pr48932_caller_unuse, (Int,)) ci = mi.cache @test isdefined(ci, :next) @@ -266,7 +268,7 @@ begin take!(GLOBAL_BUFFER) # this redefinition below should invalidate the cache of `pr48932_callee_inlined` but not that of `pr48932_caller_inlined` @noinline pr48932_callee_inlined(@nospecialize x) = (print(GLOBAL_BUFFER, x); nothing) - @test isempty(Base.specializations(Base.only(Base.methods(pr48932_callee_inlined)))) + @test isempty(Base.specializations(Base.only(Base.methods(pr48932_callee_inlined, Tuple{Any})))) let mi = Base.method_instance(pr48932_caller_inlined, (Int,)) ci = mi.cache @test isdefined(ci, :next) diff --git a/test/reflection.jl b/test/reflection.jl index f2444a1cb8658..4a738dd3e58ee 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -474,7 +474,7 @@ fLargeTable() = 4 fLargeTable(::Union, ::Union) = "a" @test fLargeTable(Union{Int, Missing}, Union{Int, Missing}) == "a" fLargeTable(::Union, ::Union) = "b" -@test length(methods(fLargeTable)) == 205 +@test length(methods(fLargeTable)) == 206 @test fLargeTable(Union{Int, Missing}, Union{Int, Missing}) == "b" # issue #15280 diff --git a/test/specificity.jl b/test/specificity.jl index 9b605444bad42..816a59f63e193 100644 --- a/test/specificity.jl +++ b/test/specificity.jl @@ -1,9 +1,9 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license function args_morespecific(a, b) - sp = (ccall(:jl_type_morespecific, Cint, (Any,Any), a, b) != 0) + sp = Base.morespecific(a, b) if sp # make sure morespecific(a,b) implies !morespecific(b,a) - @test ccall(:jl_type_morespecific, Cint, (Any,Any), b, a) == 0 + @test !Base.morespecific(b, a) end return sp end diff --git a/test/worlds.jl b/test/worlds.jl index 292628b8cbed3..e9d8895fc90d4 100644 --- a/test/worlds.jl +++ b/test/worlds.jl @@ -454,3 +454,27 @@ let e = ExceptionUnwrapping.X(nothing) @test ExceptionUnwrapping.result == [false, true] empty!(ExceptionUnwrapping.result) end + +fshadow() = 1 +gshadow() = fshadow() +@test fshadow() === 1 +@test gshadow() === 1 +fshadow_m1 = which(fshadow, ()) +fshadow() = 2 +fshadow() = 3 +@test fshadow() === 3 +@test gshadow() === 3 +fshadow_m3 = which(fshadow, ()) +Base.delete_method(fshadow_m1) +@test fshadow() === 3 +@test gshadow() === 3 +Base.delete_method(fshadow_m3) +fshadow_m2 = which(fshadow, ()) +@test fshadow() === 2 +@test gshadow() === 2 +Base.delete_method(fshadow_m2) +@test_throws MethodError(fshadow, (), Base.tls_world_age()) gshadow() +@test Base.morespecific(fshadow_m3, fshadow_m2) +@test Base.morespecific(fshadow_m2, fshadow_m1) +@test Base.morespecific(fshadow_m3, fshadow_m1) +@test !Base.morespecific(fshadow_m2, fshadow_m3) From 98b3f721275082cbf3c1ece9d3ae394ec305e12f Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Tue, 27 Feb 2024 06:46:22 +0530 Subject: [PATCH 13/13] Fix boundscheck in unsetindex for SubArrays (#53475) These had been copy-pasted incorrectly, and should throw an error if the indices are out of bounds. --- base/subarray.jl | 6 +++--- test/subarray.jl | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/base/subarray.jl b/base/subarray.jl index c15a4d48868fa..2b8545c2cc226 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -412,19 +412,19 @@ end function _unsetindex!(V::FastSubArray, i::Int) @inline - @boundscheck checkbounds(Bool, V, i) + @boundscheck checkbounds(V, i) @inbounds _unsetindex!(V.parent, _reindexlinear(V, i)) return V end function _unsetindex!(V::FastSubArray{<:Any,1}, i::Int) @inline - @boundscheck checkbounds(Bool, V, i) + @boundscheck checkbounds(V, i) @inbounds _unsetindex!(V.parent, _reindexlinear(V, i)) return V end function _unsetindex!(V::SubArray{T,N}, i::Vararg{Int,N}) where {T,N} @inline - @boundscheck checkbounds(Bool, V, i...) + @boundscheck checkbounds(V, i...) @inbounds _unsetindex!(V.parent, reindex(V.indices, i)...) return V end diff --git a/test/subarray.jl b/test/subarray.jl index ada53d7d91ee3..31bd69cccb5ae 100644 --- a/test/subarray.jl +++ b/test/subarray.jl @@ -1062,6 +1062,8 @@ end for i in eachindex(A) @test !isassigned(A, i) end + inds = eachindex(A) + @test_throws BoundsError Base._unsetindex!(A, last(inds) + oneunit(eltype(inds))) end @testset "dest IndexLinear, src IndexLinear" begin for p in (fill(BigInt(2)), BigInt[1, 2], BigInt[1 2; 3 4])