gnu: r-fields: Update to 11.4.
[jackhill/guix/guix.git] / gnu / packages / rust.scm
index 9444d8b..d5914f0 100644 (file)
@@ -1,13 +1,14 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2016 David Craven <david@craven.ch>
 ;;; Copyright © 2016 Eric Le Bihan <eric.le.bihan.dev@free.fr>
-;;; Copyright © 2016 ng0 <ng0@n0.is>
+;;; Copyright © 2016 Nikita <nikita@n0.is>
 ;;; Copyright © 2017 Ben Woodcroft <donttrustben@gmail.com>
 ;;; Copyright © 2017, 2018 Nikolai Merinov <nikolai.merinov@member.fsf.org>
-;;; Copyright © 2017 Efraim Flashner <efraim@flashner.co.il>
-;;; Copyright © 2018 Tobias Geerinckx-Rice <me@tobias.gr>
+;;; Copyright © 2017, 2019 Efraim Flashner <efraim@flashner.co.il>
+;;; Copyright © 2018, 2019 Tobias Geerinckx-Rice <me@tobias.gr>
 ;;; Copyright © 2018 Danny Milosavljevic <dannym+a@scratchpost.org>
 ;;; Copyright © 2019 Ivan Petkov <ivanppetkov@gmail.com>
+;;; Copyright © 2020 Jakub Kądziołka <kuba@kadziolka.net>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
   #:use-module (ice-9 match)
   #:use-module (srfi srfi-26))
 
+;; This is the hash for the empty file, and the reason it's relevant is not
+;; the most obvious.
+;;
+;; The root of the problem is that Cargo keeps track of a file called
+;; Cargo.lock, that contains the hash of the tarball source of each dependency.
+;;
+;; However, tarball sources aren't handled well by Guix because of the need to
+;; patch shebangs in any helper scripts. This is why we use Cargo's vendoring
+;; capabilities, where instead of the tarball, a directory is provided in its
+;; place. (In the case of rustc, the source code already ships with vendored
+;; dependencies, but crates built with cargo-build-system undergo vendoring
+;; during the build.)
+;;
+;; To preserve the advantages of checksumming, vendored dependencies contain
+;; a file called .cargo-checksum.json, which contains the hash of the tarball,
+;; as well as the list of files in it, with the hash of each file.
+;;
+;; The patch-cargo-checksums phase of cargo-build-system runs after
+;; any Guix-specific patches to the vendored dependencies and regenerates the
+;; .cargo-checksum.json files, but it's hard to know the tarball checksum that
+;; should be written to the file - and taking care of any unhandled edge case
+;; would require rebuilding everything that depends on rust. This is why we lie,
+;; and say that the tarball has the hash of an empty file. It's not a problem
+;; because cargo-build-system removes the Cargo.lock file. We can't do that
+;; for rustc because of a quirk of its build system, so we modify the lock file
+;; to substitute the hash.
 (define %cargo-reference-hash
   "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
 
   (let ((rustc-version "1.19.0"))
     (package
       (name "mrustc")
-      (version "0.8.0")
+      (version "0.9")
       (source (origin
                 (method git-fetch)
                 (uri (git-reference
-                      (url "https://github.com/thepowersgang/mrustc.git")
+                      (url "https://github.com/thepowersgang/mrustc")
                       (commit (string-append "v" version))))
                 (file-name (git-file-name name version))
                 (sha256
                  (base32
-                  "0a7v8ccyzp1sdkwni8h1698hxpfz2sxhcpx42n6l2pbm0rbjp08i"))
-                (patches
-                 (search-patches "mrustc-0.8.0-fix-variable-length-integer-receiving.patch"))))
+                  "194ny7vsks5ygiw7d8yxjmp1qwigd71ilchis6xjl6bb2sj97rd2"))))
       (outputs '("out" "cargo"))
       (build-system gnu-build-system)
       (inputs
-       `(("llvm" ,llvm-3.9.1)))
+       `(("zlib" ,zlib)))
       (native-inputs
        `(("bison" ,bison)
          ("flex" ,flex)
          ;; Required for the libstd sources.
          ("rustc" ,(package-source rust-1.19))))
       (arguments
-       `(#:test-target "local_tests"
-         #:make-flags (list (string-append "LLVM_CONFIG="
-                                           (assoc-ref %build-inputs "llvm")
-                                           "/bin/llvm-config"))
+       `(#:test-target "test"
+         #:make-flags
+         (list ,(string-append "RUSTC_TARGET="
+                               (or (%current-target-system)
+                                   (nix-system->gnu-triplet-for-rust))))
          #:phases
          (modify-phases %standard-phases
           (add-after 'unpack 'patch-date
             (lambda _
               (substitute* "Makefile"
                (("shell date") "shell date -d @1"))
+              (substitute* "run_rustc/Makefile"
+               (("[$]Vtime ") "$V "))
               #t))
            (add-after 'patch-date 'unpack-target-compiler
              (lambda* (#:key inputs outputs #:allow-other-keys)
-               (substitute* "minicargo.mk"
-                 ;; Don't try to build LLVM.
-                 (("^[$][(]LLVM_CONFIG[)]:") "xxx:")
-                 ;; Build for the correct target architecture.
-                 (("^RUSTC_TARGET := x86_64-unknown-linux-gnu")
-                  (string-append "RUSTC_TARGET := "
-                                 ,(or (%current-target-system)
-                                      (nix-system->gnu-triplet-for-rust)))))
                (invoke "tar" "xf" (assoc-ref inputs "rustc"))
-               (chdir "rustc-1.19.0-src")
-               (invoke "patch" "-p0" "../rust_src.patch")
+               (chdir ,(string-append "rustc-" rustc-version "-src"))
+               (invoke "patch" "-p0" ,(string-append "../rustc-" rustc-version
+                                                     "-src.patch"))
                (chdir "..")
+               (setenv "RUSTC_VERSION" ,rustc-version)
+               (setenv "MRUSTC_TARGET_VER"
+                ,(version-major+minor rustc-version))
+               (setenv "OUTDIR_SUF" "")
                #t))
            (replace 'configure
              (lambda* (#:key inputs #:allow-other-keys)
-               (setenv "CC" (string-append (assoc-ref inputs "gcc") "/bin/gcc"))
+               (setenv "CC" (string-append (assoc-ref inputs "gcc")
+                                           "/bin/gcc"))
+               (setenv "CXX" (string-append (assoc-ref inputs "gcc")
+                                            "/bin/g++"))
                #t))
            (add-after 'build 'build-minicargo
-             (lambda _
-               (for-each (lambda (target)
-                           (invoke "make" "-f" "minicargo.mk" target))
-                         '("output/libstd.hir" "output/libpanic_unwind.hir"
-                           "output/libproc_macro.hir" "output/libtest.hir"))
-               ;; Technically the above already does it - but we want to be clear.
-               (invoke "make" "-C" "tools/minicargo")))
+             (lambda* (#:key make-flags #:allow-other-keys)
+               ;; TODO: minicargo.mk: RUSTC_VERSION=$(RUSTC_VERSION) RUSTC_CHANNEL=$(RUSTC_SRC_TY) OUTDIR_SUF=$(OUTDIR_SUF)
+               (apply invoke "make" "-f" "minicargo.mk" "LIBS" make-flags)
+               (apply invoke "make" "-C" "tools/minicargo" make-flags)))
+           ;(add-after 'check 'check-locally
+           ;  (lambda* (#:key make-flags #:allow-other-keys)
+           ;    ;; The enum test wouldn't work otherwise.
+           ;    ;; See <https://github.com/thepowersgang/mrustc/issues/137>.
+           ;    (setenv "MRUSTC_TARGET_VER" ,(version-major+minor rustc-version))
+           ;    (apply invoke "make" "local_tests" make-flags)))
            (replace 'install
              (lambda* (#:key inputs outputs #:allow-other-keys)
                (let* ((out (assoc-ref outputs "out"))
                       (cargo-bin (string-append cargo-out "/bin"))
                       (lib (string-append out "/lib"))
                       (lib/rust (string-append lib "/mrust"))
-                      (gcc (assoc-ref inputs "gcc")))
+                      (gcc (assoc-ref inputs "gcc"))
+                      (run_rustc (string-append out
+                                                "/share/mrustc/run_rustc")))
                  ;; These files are not reproducible.
                  (for-each delete-file (find-files "output" "\\.txt$"))
-                 (delete-file-recursively "output/local_tests")
-                 (mkdir-p lib)
+                 ;(delete-file-recursively "output/local_tests")
+                 (mkdir-p (dirname lib/rust))
                  (copy-recursively "output" lib/rust)
                  (mkdir-p bin)
                  (mkdir-p tools-bin)
                  ;; minicargo uses relative paths to resolve mrustc.
                  (install-file "tools/bin/minicargo" tools-bin)
                  (install-file "tools/bin/minicargo" cargo-bin)
+                 (mkdir-p run_rustc)
+                 (copy-file "run_rustc/Makefile"
+                            (string-append run_rustc "/Makefile"))
                  #t))))))
-      (synopsis "Compiler for the Rust progamming language")
+      (synopsis "Compiler for the Rust programming language")
       (description "Rust is a systems programming language that provides memory
 safety and thread safety guarantees.")
       (home-page "https://github.com/thepowersgang/mrustc")
@@ -191,12 +227,12 @@ safety and thread safety guarantees.")
         (sha256 (base32 "0l8c14qsf42rmkqy92ahij4vf356dbyspxcips1aswpvad81y8qm"))
         (modules '((guix build utils)))
         (snippet '(begin (delete-file-recursively "src/llvm") #t))
-        (patches (map search-patch '("rust-1.19-mrustc.patch")))))
+        (patches (search-patches "rust-1.19-mrustc.patch"))))
     (outputs '("out" "cargo"))
     (properties '((timeout . 72000)               ;20 hours
                   (max-silent-time . 18000)))     ;5 hours (for armel)
     (arguments
-     `(#:imported-modules ,%cargo-utils-modules ;for `generate-checksums'
+     `(#:imported-modules ,%cargo-utils-modules ;for `generate-all-checksums'
        #:modules ((guix build utils) (ice-9 match) (guix build gnu-build-system))
        #:phases
        (modify-phases %standard-phases
@@ -270,19 +306,11 @@ test = { path = \"../libtest\" }
              #t))
          (add-after 'patch-source-shebangs 'patch-cargo-checksums
            (lambda* _
+             (use-modules (guix build cargo-utils))
              (substitute* "src/Cargo.lock"
                (("(\"checksum .* = )\".*\"" all name)
                 (string-append name "\"" ,%cargo-reference-hash "\"")))
-             (for-each
-              (lambda (filename)
-                (use-modules (guix build cargo-utils))
-                (delete-file filename)
-                (let* ((dir (dirname filename)))
-                  (display (string-append
-                            "patch-cargo-checksums: generate-checksums for "
-                            dir "\n"))
-                  (generate-checksums dir)))
-              (find-files "src/vendor" ".cargo-checksum.json"))
+             (generate-all-checksums "src/vendor")
              #t))
          ;; This phase is overridden by newer versions.
          (replace 'configure
@@ -297,8 +325,12 @@ test = { path = \"../libtest\" }
                (setenv "CFG_RELEASE_CHANNEL" "stable")
                (setenv "CFG_LIBDIR_RELATIVE" "lib")
                (setenv "CFG_VERSION" "1.19.0-stable-mrustc")
+               (setenv "MRUSTC_TARGET_VER" ,(version-major+minor version))
                ; bad: (setenv "CFG_PREFIX" "mrustc") ; FIXME output path.
                (mkdir-p "output")
+               ;; mrustc 0.9 doesn't check the search paths for crates anymore.
+               (copy-recursively (string-append rustc-bootstrap "/lib/mrust")
+                                 "output")
                (invoke (string-append rustc-bootstrap "/tools/bin/minicargo")
                        "src/rustc" "--vendor-dir" "src/vendor"
                        "--output-dir" "output/rustc-build"
@@ -387,7 +419,7 @@ test = { path = \"../libtest\" }
     (build-system gnu-build-system)
     (native-inputs
      `(("bison" ,bison) ; For the tests
-       ("cmake" ,cmake)
+       ("cmake" ,cmake-minimal)
        ("flex" ,flex) ; For the tests
        ("gdb" ,gdb)   ; For the tests
        ("procps" ,procps) ; For the tests
@@ -399,7 +431,7 @@ test = { path = \"../libtest\" }
     (inputs
      `(("jemalloc" ,jemalloc-4.5.0)
        ("llvm" ,llvm-3.9.1)
-       ("openssl" ,openssl)
+       ("openssl" ,openssl-1.0)
        ("libssh2" ,libssh2) ; For "cargo"
        ("libcurl" ,curl)))  ; For "cargo"
 
@@ -412,7 +444,7 @@ test = { path = \"../libtest\" }
             (files '("include")))
            (search-path-specification
             (variable "CPLUS_INCLUDE_PATH")
-            (files '("include")))
+            (files '("include/c++" "include")))
            (search-path-specification
             (variable "LIBRARY_PATH")
             (files '("lib" "lib64")))))
@@ -438,6 +470,10 @@ safety and thread safety guarantees.")
                       (delete-file-recursively "src/llvm")
                       #t))
           (patches '())))
+      (native-inputs
+       `(;; The tests fail with newer versions of GNU Make.
+         ("make" ,gnu-make-4.2)
+         ,@(package-native-inputs base-rust)))
       (outputs '("out" "doc" "cargo"))
       ;; Since rust-1.19 is local, it's quite probable that Hydra
       ;; will build rust-1.19 only as a dependency of rust-1.20.
@@ -682,8 +718,8 @@ jemalloc = \"" jemalloc "/lib/libjemalloc_pic.a" "\"
                       (delete-file-recursively "src/llvm")
                       (delete-file-recursively "src/llvm-emscripten")
                       #t))
-          (patches (map search-patch
-                        '("rust-1.25-accept-more-detailed-gdb-lines.patch")))))
+          (patches (search-patches
+                     "rust-1.25-accept-more-detailed-gdb-lines.patch"))))
       (arguments
        (substitute-keyword-arguments (package-arguments base-rust)
          ((#:phases phases)
@@ -717,9 +753,9 @@ jemalloc = \"" jemalloc "/lib/libjemalloc_pic.a" "\"
       (source
         (origin
           (inherit (package-source base-rust))
-          (patches (map search-patch
-                        '("rust-coresimd-doctest.patch"
-                          "rust-1.25-accept-more-detailed-gdb-lines.patch")))))
+          (patches (search-patches
+                     "rust-coresimd-doctest.patch"
+                     "rust-1.25-accept-more-detailed-gdb-lines.patch"))))
       (arguments
        (substitute-keyword-arguments (package-arguments base-rust)
          ((#:phases phases)
@@ -762,6 +798,7 @@ jemalloc = \"" jemalloc "/lib/libjemalloc_pic.a" "\"
                    (("fn finds_author_git") "#[ignore]\nfn finds_author_git")
                    (("fn finds_local_author_git") "#[ignore]\nfn finds_local_author_git"))
                  #t))
+             ;; TODO(rebuild-rust): Remove this phase in rust-1.28 when rebuilding.
              (add-after 'patch-cargo-tests 'disable-cargo-test-for-nightly-channel
                (lambda* _
                  ;; This test failed to work on "nightly" channel builds
@@ -786,10 +823,15 @@ jemalloc = \"" jemalloc "/lib/libjemalloc_pic.a" "\"
       (source
         (origin
           (inherit (package-source base-rust))
-          (patches (map search-patch '("rust-coresimd-doctest.patch"
-                                       "rust-bootstrap-stage0-test.patch"
-                                       "rust-1.25-accept-more-detailed-gdb-lines.patch"
-                                       "rust-reproducible-builds.patch")))))
+          (patches (search-patches "rust-coresimd-doctest.patch"
+                                   "rust-bootstrap-stage0-test.patch"
+                                   "rust-1.25-accept-more-detailed-gdb-lines.patch"
+                                   "rust-reproducible-builds.patch"))))
+      (native-inputs
+       ;; FIXME: Rust 1.27 and some later versions require GDB 8.2 specifically.
+       ;; See <https://bugs.gnu.org/37810>.
+       (alist-replace "gdb" (list gdb-8.2)
+                      (package-native-inputs base-rust)))
       (arguments
        (substitute-keyword-arguments (package-arguments base-rust)
          ((#:phases phases)
@@ -817,10 +859,10 @@ jemalloc = \"" jemalloc "/lib/libjemalloc_pic.a" "\"
       (source
         (origin
           (inherit (package-source base-rust))
-          (patches (map search-patch '("rust-coresimd-doctest.patch"
-                                       "rust-bootstrap-stage0-test.patch"
-                                       "rust-1.25-accept-more-detailed-gdb-lines.patch"
-                                       "rust-reproducible-builds.patch")))))
+          (patches (search-patches "rust-coresimd-doctest.patch"
+                                   "rust-bootstrap-stage0-test.patch"
+                                   "rust-1.25-accept-more-detailed-gdb-lines.patch"
+                                   "rust-reproducible-builds.patch"))))
       (inputs
        ;; Use LLVM 6.0
        (alist-replace "llvm" (list llvm-6)
@@ -853,8 +895,8 @@ jemalloc = \"" jemalloc "/lib/libjemalloc_pic.a" "\"
       (source
         (origin
           (inherit (package-source base-rust))
-          (patches (map search-patch '("rust-1.25-accept-more-detailed-gdb-lines.patch"
-                                       "rust-reproducible-builds.patch"))))))))
+          (patches (search-patches "rust-1.25-accept-more-detailed-gdb-lines.patch"
+                                   "rust-reproducible-builds.patch")))))))
 
 (define-public rust-1.30
   (let ((base-rust
@@ -902,9 +944,30 @@ jemalloc = \"" jemalloc "/lib/libjemalloc_pic.a" "\"
              (replace 'disable-amd64-avx-test
                (lambda _
                  (substitute* "src/test/ui/run-pass/issues/issue-44056.rs"
-                 (("only-x86_64") "ignore-test"))
+                  (("only-x86_64") "ignore-test"))
                   #t)))))))))
 
+(define (patch-command-exec-tests-phase test-path)
+  "The command-exec.rs test moves around between releases.  We need to apply
+a Guix-specific patch to it for each release.  This function generates the phase
+that applies said patch, parametrized by the test-path.  This is done this way
+because the phase is more complex than the equivalents for other tests that
+move around."
+ `(lambda* (#:key inputs #:allow-other-keys)
+    (let ((coreutils (assoc-ref inputs "coreutils")))
+      (substitute* ,test-path
+        ;; This test suite includes some tests that the stdlib's
+        ;; `Command` execution properly handles situations where
+        ;; the environment or PATH variable are empty, but this
+        ;; fails since we don't have `echo` available in the usual
+        ;; Linux directories.
+        ;; NB: the leading space is so we don't fail a tidy check
+        ;; for trailing whitespace, and the newlines are to ensure
+        ;; we don't exceed the 100 chars tidy check as well
+        ((" Command::new\\(\"echo\"\\)")
+         (string-append "\nCommand::new(\"" coreutils "/bin/echo\")\n")))
+      #t)))
+
 (define-public rust-1.31
   (let ((base-rust
          (rust-bootstrapped-package rust-1.30 "1.31.1"
@@ -916,26 +979,14 @@ jemalloc = \"" jemalloc "/lib/libjemalloc_pic.a" "\"
          ((#:phases phases)
           `(modify-phases ,phases
              (add-after 'patch-tests 'patch-command-exec-tests
-               (lambda* (#:key inputs #:allow-other-keys)
-                 (let ((coreutils (assoc-ref inputs "coreutils")))
-                   (substitute* "src/test/run-pass/command-exec.rs"
-                     ;; This test suite includes some tests that the stdlib's
-                     ;; `Command` execution properly handles situations where
-                     ;; the environment or PATH variable are empty, but this
-                     ;; fails since we don't have `echo` available in the usual
-                     ;; Linux directories.
-                     ;; NB: the leading space is so we don't fail a tidy check
-                     ;; for trailing whitespace, and the newlines are to ensure
-                     ;; we don't exceed the 100 chars tidy check as well
-                     ((" Command::new\\(\"echo\"\\)")
-                      (string-append "\nCommand::new(\"" coreutils "/bin/echo\")\n")))
-                   #t)))
-             ;; The test has been moved elsewhere.
-             (replace 'disable-amd64-avx-test
-               (lambda _
-                 (substitute* "src/test/ui/issues/issue-44056.rs"
-                   (("only-x86_64") "ignore-test"))
-                  #t))
+               ,(patch-command-exec-tests-phase
+                  "src/test/run-pass/command-exec.rs"))
+             ;; The test has been moved elsewhere.
+             (replace 'disable-amd64-avx-test
+               (lambda _
+                 (substitute* "src/test/ui/issues/issue-44056.rs"
+                  (("only-x86_64") "ignore-test"))
+                 #t))
              (add-after 'patch-tests 'patch-process-docs-rev-cmd
                (lambda* _
                  ;; Disable some doc tests which depend on the "rev" command
@@ -959,7 +1010,7 @@ jemalloc = \"" jemalloc "/lib/libjemalloc_pic.a" "\"
                            (delete-file-recursively "src/tools/lldb")
                            (delete-file-recursively "vendor/jemalloc-sys/jemalloc")
                            #t))
-          (patches (map search-patch '("rust-reproducible-builds.patch")))
+          (patches (search-patches "rust-reproducible-builds.patch"))
           ;; the vendor directory has moved to the root of
           ;; the tarball, so we have to strip an extra prefix
           (patch-flags '("-p2"))))
@@ -975,19 +1026,11 @@ jemalloc = \"" jemalloc "/lib/libjemalloc_pic.a" "\"
              ;; root of the rust tarball
              (replace 'patch-cargo-checksums
                (lambda* _
+                 (use-modules (guix build cargo-utils))
                  (substitute* "Cargo.lock"
                    (("(\"checksum .* = )\".*\"" all name)
                     (string-append name "\"" ,%cargo-reference-hash "\"")))
-                 (for-each
-                  (lambda (filename)
-                    (use-modules (guix build cargo-utils))
-                    (delete-file filename)
-                    (let* ((dir (dirname filename)))
-                      (display (string-append
-                                "patch-cargo-checksums: generate-checksums for "
-                                dir "\n"))
-                      (generate-checksums dir)))
-                  (find-files "vendor" ".cargo-checksum.json"))
+                 (generate-all-checksums "vendor")
                  #t))
              (add-after 'enable-codegen-tests 'override-jemalloc
                (lambda* (#:key inputs #:allow-other-keys)
@@ -1050,7 +1093,7 @@ jemalloc = \"" jemalloc "/lib/libjemalloc_pic.a" "\"
                       (delete-file-recursively "vendor/jemalloc-sys/jemalloc")
                       #t)))))))
 
-(define-public rust
+(define-public rust-1.35
   (let ((base-rust
          (rust-bootstrapped-package rust-1.34 "1.35.0"
            "0bbizy6b7002v1rdhrxrf5gijclbyizdhkglhp81ib3bf5x66kas")))
@@ -1072,3 +1115,211 @@ jemalloc = \"" jemalloc "/lib/libjemalloc_pic.a" "\"
                  (substitute* "src/tools/tidy/src/main.rs"
                    (("bins::check") "//bins::check"))
                  #t)))))))))
+
+(define-public rust-1.36
+  (let ((base-rust
+         (rust-bootstrapped-package rust-1.35 "1.36.0"
+           "06xv2p6zq03lidr0yaf029ii8wnjjqa894nkmrm6s0rx47by9i04")))
+    (package
+      (inherit base-rust)
+      (arguments
+       (substitute-keyword-arguments (package-arguments base-rust)
+         ((#:phases phases)
+          `(modify-phases ,phases
+             (delete 'patch-process-docs-rev-cmd))))))))
+
+(define-public rust-1.37
+  (let ((base-rust
+         (rust-bootstrapped-package rust-1.36 "1.37.0"
+           "1hrqprybhkhs6d9b5pjskfnc5z9v2l2gync7nb39qjb5s0h703hj")))
+    (package
+      (inherit base-rust)
+      (arguments
+       (substitute-keyword-arguments (package-arguments base-rust)
+         ((#:phases phases)
+          `(modify-phases ,phases
+             (add-before 'configure 'configure-cargo-home
+               (lambda _
+                 (let ((cargo-home (string-append (getcwd) "/.cargo")))
+                   (mkdir-p cargo-home)
+                   (setenv "CARGO_HOME" cargo-home)
+                   #t))))))))))
+
+;; TODO(rebuild-rust): Switch to LLVM 9 in 1.38 instead of 1.40.
+(define-public rust-1.38
+  (let ((base-rust
+         (rust-bootstrapped-package rust-1.37 "1.38.0"
+           "101dlpsfkq67p0hbwx4acqq6n90dj4bbprndizpgh1kigk566hk4")))
+    (package
+      (inherit base-rust)
+      #;(inputs
+        (alist-replace "llvm" (list llvm-9)
+                       (package-inputs base-rust)))
+      (arguments
+       (substitute-keyword-arguments (package-arguments base-rust)
+         ((#:phases phases)
+          `(modify-phases ,phases
+             (replace 'patch-command-exec-tests
+               ,(patch-command-exec-tests-phase
+                  "src/test/ui/command-exec.rs"))
+             (add-after 'patch-tests 'patch-command-uid-gid-test
+               (lambda _
+                 (substitute* "src/test/ui/command-uid-gid.rs"
+                   (("/bin/sh") (which "sh"))
+                   (("ignore-sgx") "ignore-sgx\n// ignore-tidy-linelength"))
+                 #t)))))))))
+
+(define-public rust-1.39
+  (let ((base-rust
+         (rust-bootstrapped-package rust-1.38 "1.39.0"
+           "0mwkc1bnil2cfyf6nglpvbn2y0zfbv44zfhsd5qg4c9rm6vgd8dl")))
+    (package
+      (inherit base-rust)
+      (arguments
+       (substitute-keyword-arguments (package-arguments base-rust)
+         ((#:phases phases)
+          `(modify-phases ,phases
+             (replace 'patch-cargo-checksums
+               ;; The Cargo.lock format changed.
+               (lambda* _
+                 (use-modules (guix build cargo-utils))
+                 (substitute* "Cargo.lock"
+                   (("(checksum = )\".*\"" all name)
+                    (string-append name "\"" ,%cargo-reference-hash "\"")))
+                 (generate-all-checksums "vendor")
+                 #t)))))))))
+
+(define-public rust-1.40
+  (let ((base-rust
+         (rust-bootstrapped-package rust-1.39 "1.40.0"
+           "1ba9llwhqm49w7sz3z0gqscj039m53ky9wxzhaj11z6yg1ah15yx")))
+    (package
+      (inherit base-rust)
+      (inputs
+        (alist-replace "llvm" (list llvm-9)
+                       (package-inputs base-rust)))
+      (source
+        (origin
+          (inherit (package-source base-rust))
+          ;; llvm-emscripten is no longer bundled, as that codegen backend
+          ;; got removed.
+          (snippet '(begin
+                      (delete-file-recursively "src/llvm-project")
+                      (delete-file-recursively "vendor/jemalloc-sys/jemalloc")
+                      #t))))
+      (arguments
+       ;; Rust 1.40 does not ship rustc-internal libraries by default
+       ;; (see rustc-dev-split). This means that librustc_driver.so is no
+       ;; longer available in lib/rustlib/$target/lib, which is the directory
+       ;; included in the runpath of librustc_codegen_llvm-llvm.so.
+       ;; This is detected by our validate-runpath phase as an error, but it
+       ;; is harmless as the codegen backend is loaded by librustc_driver.so
+       ;; itself, which must at that point have been already loaded.
+       ;; As such, we skip validating the runpath for Rust 1.40.
+       ;; Rust 1.41 stopped putting the codegen backend in a separate library,
+       ;; which makes this workaround only necessary for this release.
+       (cons* #:validate-runpath? #f
+         (substitute-keyword-arguments (package-arguments base-rust)
+           ((#:phases phases)
+            `(modify-phases ,phases
+               ;; We often need to patch tests with various Guix-specific paths.
+               ;; This often increases the line length and makes tidy, rustc's
+               ;; style checker, complain. We could insert additional newlines
+               ;; or add an "// ignore-tidy-linelength" comment, but as an
+               ;; ignore comment must be used, both approaches are fragile due
+               ;; to upstream formatting changes. As such, disable running the
+               ;; linter during tests, since it's intended for rustc developers
+               ;; anyway.
+               ;;
+               ;; TODO(rebuild-rust): This phase could be added earlier to
+               ;; simplify a significant amount of code, but it would require
+               ;; rebuilding the entire rusty universe.
+               (add-after 'patch-tests 'neuter-tidy
+                 (lambda _
+                   (substitute* "src/bootstrap/builder.rs"
+                     (("^.*::Tidy,") ""))
+                   #t))
+               ;; TODO(rebuild-rust): Adapt the find-files approach for
+               ;; earlier testsuite patches.
+               (replace 'patch-command-uid-gid-test
+                 (lambda _
+                   (match (find-files "src/test" "command-uid-gid\\.rs")
+                     ((file)
+                      (substitute* file
+                        (("/bin/sh") (which "sh")))))
+                   #t))
+               (replace 'patch-command-exec-tests
+                 ,(patch-command-exec-tests-phase
+                    '(match (find-files "src/test" "command-exec\\.rs")
+                       ((file) file))))
+               ;; TODO(rebuild-rust): The test in question got fixed long ago.
+               (delete 'disable-cargo-test-for-nightly-channel)
+               ;; The test got removed in commit 000fe63b6fc57b09828930cacbab20c2ee6e6d15
+               ;; "Remove painful test that is not pulling its weight"
+               (delete 'remove-unsupported-tests)))))))))
+
+(define-public rust-1.41
+  (let ((base-rust
+         (rust-bootstrapped-package rust-1.40 "1.41.1"
+           "0ws5x0fxv57fyllsa6025h3q6j9v3m8nb3syl4x0hgkddq0kvj9q")))
+    (package
+      (inherit base-rust)
+      (arguments
+       (substitute-keyword-arguments (package-arguments base-rust)
+         ((#:validate-runpath? _) #t))))))
+
+(define-public rust-1.42
+  (rust-bootstrapped-package rust-1.41 "1.42.0"
+    "0x9lxs82may6c0iln0b908cxyn1cv7h03n5cmbx3j1bas4qzks6j"))
+
+(define-public rust-1.43
+  (rust-bootstrapped-package rust-1.42 "1.43.0"
+    "18akhk0wz1my6y9vhardriy2ysc482z0fnjdcgs9gy59kmnarxkm"))
+
+(define-public rust-1.44
+  (rust-bootstrapped-package rust-1.43 "1.44.1"
+    "0ww4z2v3gxgn3zddqzwqya1gln04p91ykbrflnpdbmcd575n8bky"))
+
+(define-public rust-1.45
+  (let ((base-rust
+         (rust-bootstrapped-package rust-1.44 "1.45.2"
+           "0273a1g3f59plyi1n0azf21qjzwml1yqdnj5z472crz37qggr8xp")))
+    (package
+      (inherit base-rust)
+      (source
+        (origin
+          (inherit (package-source base-rust))
+          (patches (search-patches "rust-1.45-linker-locale.patch"))))
+      (inputs
+        (alist-replace "llvm" (list llvm-10)
+                       (package-inputs base-rust)))
+      (arguments
+        (substitute-keyword-arguments (package-arguments base-rust)
+          ((#:phases phases)
+           `(modify-phases ,phases
+              ;; These tests make sure that the parser behaves properly when
+              ;; a source file starts with a shebang. Unfortunately,
+              ;; the patch-shebangs phase changes the meaning of these edge-cases.
+              ;; We skip the test since it's drastically unlikely Guix's packaging
+              ;; will introduce a bug here.
+              (add-after 'patch-tests 'skip-shebang-tests
+                (lambda _
+                  (with-directory-excursion "src/test/ui/parser/shebang"
+                    (delete-file "shebang-doc-comment.rs")
+                    (delete-file "sneaky-attrib.rs")
+                    #t)))
+              ;; This test case synchronizes itself by starting a localhost TCP
+              ;; server. This doesn't work as networking is not available.
+              (add-after 'patch-tests 'skip-networking-test
+                (lambda _
+                  (substitute* "src/tools/cargo/tests/testsuite/freshness.rs"
+                    (("fn linking_interrupted" all)
+                     (string-append "#[ignore] " all)))
+                 #t)))))))))
+
+(define-public rust-1.46
+  (rust-bootstrapped-package rust-1.45 "1.46.0"
+    "0a17jby2pd050s24cy4dfc0gzvgcl585v3vvyfilniyvjrqknsid"))
+
+;; TODO(staging): Bump this variable to the latest packaged rust.
+(define-public rust rust-1.39)