Merge from rust-lang/rust

This commit is contained in:
Laurențiu Nicola 2024-12-11 11:49:08 +02:00
commit 5db2aa865c
2585 changed files with 34566 additions and 24459 deletions

View file

@ -324,9 +324,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.162"
version = "0.2.167"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398"
checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc"
[[package]]
name = "libredox"
@ -558,9 +558,9 @@ dependencies = [
[[package]]
name = "sysinfo"
version = "0.31.4"
version = "0.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "355dbe4f8799b304b05e1b0f05fc59b2a18d36645cf169607da45bde2f69a1be"
checksum = "948512566b1895f93b1592c7574baeb2de842f224f2aab158799ecadb8ebbb46"
dependencies = [
"core-foundation-sys",
"libc",

View file

@ -63,7 +63,7 @@ walkdir = "2.4"
xz2 = "0.1"
# Dependencies needed by the build-metrics feature
sysinfo = { version = "0.31.2", default-features = false, optional = true, features = ["system"] }
sysinfo = { version = "0.33.0", default-features = false, optional = true, features = ["system"] }
[target.'cfg(windows)'.dependencies.junction]
version = "1.0.0"

File diff suppressed because it is too large Load diff

View file

@ -16,8 +16,9 @@ from shutil import rmtree
bootstrap_dir = os.path.dirname(os.path.abspath(__file__))
# For the import below, have Python search in src/bootstrap first.
sys.path.insert(0, bootstrap_dir)
import bootstrap # noqa: E402
import configure # noqa: E402
import bootstrap # noqa: E402
import configure # noqa: E402
def serialize_and_parse(configure_args, bootstrap_args=None):
from io import StringIO
@ -32,15 +33,20 @@ def serialize_and_parse(configure_args, bootstrap_args=None):
try:
import tomllib
# Verify this is actually valid TOML.
tomllib.loads(build.config_toml)
except ImportError:
print("WARNING: skipping TOML validation, need at least python 3.11", file=sys.stderr)
print(
"WARNING: skipping TOML validation, need at least python 3.11",
file=sys.stderr,
)
return build
class VerifyTestCase(unittest.TestCase):
"""Test Case for verify"""
def setUp(self):
self.container = tempfile.mkdtemp()
self.src = os.path.join(self.container, "src.txt")
@ -68,14 +74,14 @@ class VerifyTestCase(unittest.TestCase):
class ProgramOutOfDate(unittest.TestCase):
"""Test if a program is out of date"""
def setUp(self):
self.container = tempfile.mkdtemp()
os.mkdir(os.path.join(self.container, "stage0"))
self.build = bootstrap.RustBuild()
self.build.date = "2017-06-15"
self.build.build_dir = self.container
self.rustc_stamp_path = os.path.join(self.container, "stage0",
".rustc-stamp")
self.rustc_stamp_path = os.path.join(self.container, "stage0", ".rustc-stamp")
self.key = self.build.date + str(None)
def tearDown(self):
@ -97,11 +103,14 @@ class ProgramOutOfDate(unittest.TestCase):
"""Return False both dates match"""
with open(self.rustc_stamp_path, "w") as rustc_stamp:
rustc_stamp.write("2017-06-15None")
self.assertFalse(self.build.program_out_of_date(self.rustc_stamp_path, self.key))
self.assertFalse(
self.build.program_out_of_date(self.rustc_stamp_path, self.key)
)
class ParseArgsInConfigure(unittest.TestCase):
"""Test if `parse_args` function in `configure.py` works properly"""
@patch("configure.err")
def test_unknown_args(self, err):
# It should be print an error message if the argument doesn't start with '--'
@ -148,28 +157,35 @@ class ParseArgsInConfigure(unittest.TestCase):
class GenerateAndParseConfig(unittest.TestCase):
"""Test that we can serialize and deserialize a config.toml file"""
def test_no_args(self):
build = serialize_and_parse([])
self.assertEqual(build.get_toml("profile"), 'dist')
self.assertEqual(build.get_toml("profile"), "dist")
self.assertIsNone(build.get_toml("llvm.download-ci-llvm"))
def test_set_section(self):
build = serialize_and_parse(["--set", "llvm.download-ci-llvm"])
self.assertEqual(build.get_toml("download-ci-llvm", section="llvm"), 'true')
self.assertEqual(build.get_toml("download-ci-llvm", section="llvm"), "true")
def test_set_target(self):
build = serialize_and_parse(["--set", "target.x86_64-unknown-linux-gnu.cc=gcc"])
self.assertEqual(build.get_toml("cc", section="target.x86_64-unknown-linux-gnu"), 'gcc')
self.assertEqual(
build.get_toml("cc", section="target.x86_64-unknown-linux-gnu"), "gcc"
)
def test_set_top_level(self):
build = serialize_and_parse(["--set", "profile=compiler"])
self.assertEqual(build.get_toml("profile"), 'compiler')
self.assertEqual(build.get_toml("profile"), "compiler")
def test_set_codegen_backends(self):
build = serialize_and_parse(["--set", "rust.codegen-backends=cranelift"])
self.assertNotEqual(build.config_toml.find("codegen-backends = ['cranelift']"), -1)
self.assertNotEqual(
build.config_toml.find("codegen-backends = ['cranelift']"), -1
)
build = serialize_and_parse(["--set", "rust.codegen-backends=cranelift,llvm"])
self.assertNotEqual(build.config_toml.find("codegen-backends = ['cranelift', 'llvm']"), -1)
self.assertNotEqual(
build.config_toml.find("codegen-backends = ['cranelift', 'llvm']"), -1
)
build = serialize_and_parse(["--enable-full-tools"])
self.assertNotEqual(build.config_toml.find("codegen-backends = ['llvm']"), -1)
@ -223,7 +239,7 @@ class BuildBootstrap(unittest.TestCase):
self.assertTrue("--timings" in args)
def test_warnings(self):
for toml_warnings in ['false', 'true', None]:
for toml_warnings in ["false", "true", None]:
configure_args = []
if toml_warnings is not None:
configure_args = ["--set", "rust.deny-warnings=" + toml_warnings]

View file

@ -6,11 +6,12 @@ from __future__ import absolute_import, division, print_function
import shlex
import sys
import os
rust_dir = os.path.dirname(os.path.abspath(__file__))
rust_dir = os.path.dirname(rust_dir)
rust_dir = os.path.dirname(rust_dir)
sys.path.append(os.path.join(rust_dir, "src", "bootstrap"))
import bootstrap # noqa: E402
import bootstrap # noqa: E402
class Option(object):
@ -32,26 +33,62 @@ def v(*args):
options.append(Option(*args, value=True))
o("debug", "rust.debug", "enables debugging environment; does not affect optimization of bootstrapped code")
o(
"debug",
"rust.debug",
"enables debugging environment; does not affect optimization of bootstrapped code",
)
o("docs", "build.docs", "build standard library documentation")
o("compiler-docs", "build.compiler-docs", "build compiler documentation")
o("optimize-tests", "rust.optimize-tests", "build tests with optimizations")
o("verbose-tests", "rust.verbose-tests", "enable verbose output when running tests")
o("ccache", "llvm.ccache", "invoke gcc/clang via ccache to reuse object files between builds")
o(
"ccache",
"llvm.ccache",
"invoke gcc/clang via ccache to reuse object files between builds",
)
o("sccache", None, "invoke gcc/clang via sccache to reuse object files between builds")
o("local-rust", None, "use an installed rustc rather than downloading a snapshot")
v("local-rust-root", None, "set prefix for local rust binary")
o("local-rebuild", "build.local-rebuild", "assume local-rust matches the current version, for rebuilds; implies local-rust, and is implied if local-rust already matches the current version")
o("llvm-static-stdcpp", "llvm.static-libstdcpp", "statically link to libstdc++ for LLVM")
o("llvm-link-shared", "llvm.link-shared", "prefer shared linking to LLVM (llvm-config --link-shared)")
o(
"local-rebuild",
"build.local-rebuild",
"assume local-rust matches the current version, for rebuilds; implies local-rust, and is implied if local-rust already matches the current version",
)
o(
"llvm-static-stdcpp",
"llvm.static-libstdcpp",
"statically link to libstdc++ for LLVM",
)
o(
"llvm-link-shared",
"llvm.link-shared",
"prefer shared linking to LLVM (llvm-config --link-shared)",
)
o("rpath", "rust.rpath", "build rpaths into rustc itself")
o("codegen-tests", "rust.codegen-tests", "run the tests/codegen tests")
o("ninja", "llvm.ninja", "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)")
o(
"ninja",
"llvm.ninja",
"build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)",
)
o("locked-deps", "build.locked-deps", "force Cargo.lock to be up to date")
o("vendor", "build.vendor", "enable usage of vendored Rust crates")
o("sanitizers", "build.sanitizers", "build the sanitizer runtimes (asan, dfsan, lsan, msan, tsan, hwasan)")
o("dist-src", "rust.dist-src", "when building tarballs enables building a source tarball")
o("cargo-native-static", "build.cargo-native-static", "static native libraries in cargo")
o(
"sanitizers",
"build.sanitizers",
"build the sanitizer runtimes (asan, dfsan, lsan, msan, tsan, hwasan)",
)
o(
"dist-src",
"rust.dist-src",
"when building tarballs enables building a source tarball",
)
o(
"cargo-native-static",
"build.cargo-native-static",
"static native libraries in cargo",
)
o("profiler", "build.profiler", "build the profiler runtime")
o("full-tools", None, "enable all tools")
o("lld", "rust.lld", "build lld")
@ -59,7 +96,11 @@ o("llvm-bitcode-linker", "rust.llvm-bitcode-linker", "build llvm bitcode linker"
o("clang", "llvm.clang", "build clang")
o("use-libcxx", "llvm.use-libcxx", "build LLVM with libc++")
o("control-flow-guard", "rust.control-flow-guard", "Enable Control Flow Guard")
o("patch-binaries-for-nix", "build.patch-binaries-for-nix", "whether patch binaries for usage with Nix toolchains")
o(
"patch-binaries-for-nix",
"build.patch-binaries-for-nix",
"whether patch binaries for usage with Nix toolchains",
)
o("new-symbol-mangling", "rust.new-symbol-mangling", "use symbol-mangling-version v0")
v("llvm-cflags", "llvm.cflags", "build LLVM with these extra compiler flags")
@ -76,16 +117,48 @@ o("llvm-enzyme", "llvm.enzyme", "build LLVM with enzyme")
o("llvm-offload", "llvm.offload", "build LLVM with gpu offload support")
o("llvm-plugins", "llvm.plugins", "build LLVM with plugin interface")
o("debug-assertions", "rust.debug-assertions", "build with debugging assertions")
o("debug-assertions-std", "rust.debug-assertions-std", "build the standard library with debugging assertions")
o(
"debug-assertions-std",
"rust.debug-assertions-std",
"build the standard library with debugging assertions",
)
o("overflow-checks", "rust.overflow-checks", "build with overflow checks")
o("overflow-checks-std", "rust.overflow-checks-std", "build the standard library with overflow checks")
o("llvm-release-debuginfo", "llvm.release-debuginfo", "build LLVM with debugger metadata")
o(
"overflow-checks-std",
"rust.overflow-checks-std",
"build the standard library with overflow checks",
)
o(
"llvm-release-debuginfo",
"llvm.release-debuginfo",
"build LLVM with debugger metadata",
)
v("debuginfo-level", "rust.debuginfo-level", "debuginfo level for Rust code")
v("debuginfo-level-rustc", "rust.debuginfo-level-rustc", "debuginfo level for the compiler")
v("debuginfo-level-std", "rust.debuginfo-level-std", "debuginfo level for the standard library")
v("debuginfo-level-tools", "rust.debuginfo-level-tools", "debuginfo level for the tools")
v("debuginfo-level-tests", "rust.debuginfo-level-tests", "debuginfo level for the test suites run with compiletest")
v("save-toolstates", "rust.save-toolstates", "save build and test status of external tools into this file")
v(
"debuginfo-level-rustc",
"rust.debuginfo-level-rustc",
"debuginfo level for the compiler",
)
v(
"debuginfo-level-std",
"rust.debuginfo-level-std",
"debuginfo level for the standard library",
)
v(
"debuginfo-level-tools",
"rust.debuginfo-level-tools",
"debuginfo level for the tools",
)
v(
"debuginfo-level-tests",
"rust.debuginfo-level-tests",
"debuginfo level for the test suites run with compiletest",
)
v(
"save-toolstates",
"rust.save-toolstates",
"save build and test status of external tools into this file",
)
v("prefix", "install.prefix", "set installation prefix")
v("localstatedir", "install.localstatedir", "local state directory")
@ -102,50 +175,117 @@ v("llvm-config", None, "set path to llvm-config")
v("llvm-filecheck", None, "set path to LLVM's FileCheck utility")
v("python", "build.python", "set path to python")
v("android-ndk", "build.android-ndk", "set path to Android NDK")
v("musl-root", "target.x86_64-unknown-linux-musl.musl-root",
"MUSL root installation directory (deprecated)")
v("musl-root-x86_64", "target.x86_64-unknown-linux-musl.musl-root",
"x86_64-unknown-linux-musl install directory")
v("musl-root-i586", "target.i586-unknown-linux-musl.musl-root",
"i586-unknown-linux-musl install directory")
v("musl-root-i686", "target.i686-unknown-linux-musl.musl-root",
"i686-unknown-linux-musl install directory")
v("musl-root-arm", "target.arm-unknown-linux-musleabi.musl-root",
"arm-unknown-linux-musleabi install directory")
v("musl-root-armhf", "target.arm-unknown-linux-musleabihf.musl-root",
"arm-unknown-linux-musleabihf install directory")
v("musl-root-armv5te", "target.armv5te-unknown-linux-musleabi.musl-root",
"armv5te-unknown-linux-musleabi install directory")
v("musl-root-armv7", "target.armv7-unknown-linux-musleabi.musl-root",
"armv7-unknown-linux-musleabi install directory")
v("musl-root-armv7hf", "target.armv7-unknown-linux-musleabihf.musl-root",
"armv7-unknown-linux-musleabihf install directory")
v("musl-root-aarch64", "target.aarch64-unknown-linux-musl.musl-root",
"aarch64-unknown-linux-musl install directory")
v("musl-root-mips", "target.mips-unknown-linux-musl.musl-root",
"mips-unknown-linux-musl install directory")
v("musl-root-mipsel", "target.mipsel-unknown-linux-musl.musl-root",
"mipsel-unknown-linux-musl install directory")
v("musl-root-mips64", "target.mips64-unknown-linux-muslabi64.musl-root",
"mips64-unknown-linux-muslabi64 install directory")
v("musl-root-mips64el", "target.mips64el-unknown-linux-muslabi64.musl-root",
"mips64el-unknown-linux-muslabi64 install directory")
v("musl-root-riscv32gc", "target.riscv32gc-unknown-linux-musl.musl-root",
"riscv32gc-unknown-linux-musl install directory")
v("musl-root-riscv64gc", "target.riscv64gc-unknown-linux-musl.musl-root",
"riscv64gc-unknown-linux-musl install directory")
v("musl-root-loongarch64", "target.loongarch64-unknown-linux-musl.musl-root",
"loongarch64-unknown-linux-musl install directory")
v("qemu-armhf-rootfs", "target.arm-unknown-linux-gnueabihf.qemu-rootfs",
"rootfs in qemu testing, you probably don't want to use this")
v("qemu-aarch64-rootfs", "target.aarch64-unknown-linux-gnu.qemu-rootfs",
"rootfs in qemu testing, you probably don't want to use this")
v("qemu-riscv64-rootfs", "target.riscv64gc-unknown-linux-gnu.qemu-rootfs",
"rootfs in qemu testing, you probably don't want to use this")
v("experimental-targets", "llvm.experimental-targets",
"experimental LLVM targets to build")
v(
"musl-root",
"target.x86_64-unknown-linux-musl.musl-root",
"MUSL root installation directory (deprecated)",
)
v(
"musl-root-x86_64",
"target.x86_64-unknown-linux-musl.musl-root",
"x86_64-unknown-linux-musl install directory",
)
v(
"musl-root-i586",
"target.i586-unknown-linux-musl.musl-root",
"i586-unknown-linux-musl install directory",
)
v(
"musl-root-i686",
"target.i686-unknown-linux-musl.musl-root",
"i686-unknown-linux-musl install directory",
)
v(
"musl-root-arm",
"target.arm-unknown-linux-musleabi.musl-root",
"arm-unknown-linux-musleabi install directory",
)
v(
"musl-root-armhf",
"target.arm-unknown-linux-musleabihf.musl-root",
"arm-unknown-linux-musleabihf install directory",
)
v(
"musl-root-armv5te",
"target.armv5te-unknown-linux-musleabi.musl-root",
"armv5te-unknown-linux-musleabi install directory",
)
v(
"musl-root-armv7",
"target.armv7-unknown-linux-musleabi.musl-root",
"armv7-unknown-linux-musleabi install directory",
)
v(
"musl-root-armv7hf",
"target.armv7-unknown-linux-musleabihf.musl-root",
"armv7-unknown-linux-musleabihf install directory",
)
v(
"musl-root-aarch64",
"target.aarch64-unknown-linux-musl.musl-root",
"aarch64-unknown-linux-musl install directory",
)
v(
"musl-root-mips",
"target.mips-unknown-linux-musl.musl-root",
"mips-unknown-linux-musl install directory",
)
v(
"musl-root-mipsel",
"target.mipsel-unknown-linux-musl.musl-root",
"mipsel-unknown-linux-musl install directory",
)
v(
"musl-root-mips64",
"target.mips64-unknown-linux-muslabi64.musl-root",
"mips64-unknown-linux-muslabi64 install directory",
)
v(
"musl-root-mips64el",
"target.mips64el-unknown-linux-muslabi64.musl-root",
"mips64el-unknown-linux-muslabi64 install directory",
)
v(
"musl-root-riscv32gc",
"target.riscv32gc-unknown-linux-musl.musl-root",
"riscv32gc-unknown-linux-musl install directory",
)
v(
"musl-root-riscv64gc",
"target.riscv64gc-unknown-linux-musl.musl-root",
"riscv64gc-unknown-linux-musl install directory",
)
v(
"musl-root-loongarch64",
"target.loongarch64-unknown-linux-musl.musl-root",
"loongarch64-unknown-linux-musl install directory",
)
v(
"qemu-armhf-rootfs",
"target.arm-unknown-linux-gnueabihf.qemu-rootfs",
"rootfs in qemu testing, you probably don't want to use this",
)
v(
"qemu-aarch64-rootfs",
"target.aarch64-unknown-linux-gnu.qemu-rootfs",
"rootfs in qemu testing, you probably don't want to use this",
)
v(
"qemu-riscv64-rootfs",
"target.riscv64gc-unknown-linux-gnu.qemu-rootfs",
"rootfs in qemu testing, you probably don't want to use this",
)
v(
"experimental-targets",
"llvm.experimental-targets",
"experimental LLVM targets to build",
)
v("release-channel", "rust.channel", "the name of the release channel to build")
v("release-description", "rust.description", "optional descriptive string for version output")
v(
"release-description",
"rust.description",
"optional descriptive string for version output",
)
v("dist-compression-formats", None, "List of compression formats to use")
# Used on systems where "cc" is unavailable
@ -154,7 +294,11 @@ v("default-linker", "rust.default-linker", "the default linker")
# Many of these are saved below during the "writing configuration" step
# (others are conditionally saved).
o("manage-submodules", "build.submodules", "let the build manage the git submodules")
o("full-bootstrap", "build.full-bootstrap", "build three compilers instead of two (not recommended except for testing reproducible builds)")
o(
"full-bootstrap",
"build.full-bootstrap",
"build three compilers instead of two (not recommended except for testing reproducible builds)",
)
o("extended", "build.extended", "build an extended rust tool set")
v("bootstrap-cache-path", None, "use provided path for the bootstrap cache")
@ -165,8 +309,16 @@ v("host", None, "List of GNUs ./configure syntax LLVM host triples")
v("target", None, "List of GNUs ./configure syntax LLVM target triples")
# Options specific to this configure script
o("option-checking", None, "complain about unrecognized options in this configure script")
o("verbose-configure", None, "don't truncate options when printing them in this configure script")
o(
"option-checking",
None,
"complain about unrecognized options in this configure script",
)
o(
"verbose-configure",
None,
"don't truncate options when printing them in this configure script",
)
v("set", None, "set arbitrary key/value pairs in TOML configuration")
@ -178,39 +330,42 @@ def err(msg):
print("\nconfigure: ERROR: " + msg + "\n")
sys.exit(1)
def is_value_list(key):
for option in options:
if option.name == key and option.desc.startswith('List of'):
if option.name == key and option.desc.startswith("List of"):
return True
return False
if '--help' in sys.argv or '-h' in sys.argv:
print('Usage: ./configure [options]')
print('')
print('Options')
if "--help" in sys.argv or "-h" in sys.argv:
print("Usage: ./configure [options]")
print("")
print("Options")
for option in options:
if 'android' in option.name:
if "android" in option.name:
# no one needs to know about these obscure options
continue
if option.value:
print('\t{:30} {}'.format('--{}=VAL'.format(option.name), option.desc))
print("\t{:30} {}".format("--{}=VAL".format(option.name), option.desc))
else:
print('\t--enable-{:25} OR --disable-{}'.format(option.name, option.name))
print('\t\t' + option.desc)
print('')
print('This configure script is a thin configuration shim over the true')
print('configuration system, `config.toml`. You can explore the comments')
print('in `config.example.toml` next to this configure script to see')
print('more information about what each option is. Additionally you can')
print('pass `--set` as an argument to set arbitrary key/value pairs')
print('in the TOML configuration if desired')
print('')
print('Also note that all options which take `--enable` can similarly')
print('be passed with `--disable-foo` to forcibly disable the option')
print("\t--enable-{:25} OR --disable-{}".format(option.name, option.name))
print("\t\t" + option.desc)
print("")
print("This configure script is a thin configuration shim over the true")
print("configuration system, `config.toml`. You can explore the comments")
print("in `config.example.toml` next to this configure script to see")
print("more information about what each option is. Additionally you can")
print("pass `--set` as an argument to set arbitrary key/value pairs")
print("in the TOML configuration if desired")
print("")
print("Also note that all options which take `--enable` can similarly")
print("be passed with `--disable-foo` to forcibly disable the option")
sys.exit(0)
VERBOSE = False
# Parse all command line arguments into one of these three lists, handling
# boolean and value-based options separately
def parse_args(args):
@ -222,7 +377,7 @@ def parse_args(args):
while i < len(args):
arg = args[i]
i += 1
if not arg.startswith('--'):
if not arg.startswith("--"):
unknown_args.append(arg)
continue
@ -230,7 +385,7 @@ def parse_args(args):
for option in options:
value = None
if option.value:
keyval = arg[2:].split('=', 1)
keyval = arg[2:].split("=", 1)
key = keyval[0]
if option.name != key:
continue
@ -244,9 +399,9 @@ def parse_args(args):
need_value_args.append(arg)
continue
else:
if arg[2:] == 'enable-' + option.name:
if arg[2:] == "enable-" + option.name:
value = True
elif arg[2:] == 'disable-' + option.name:
elif arg[2:] == "disable-" + option.name:
value = False
else:
continue
@ -263,8 +418,9 @@ def parse_args(args):
# NOTE: here and a few other places, we use [-1] to apply the *last* value
# passed. But if option-checking is enabled, then the known_args loop will
# also assert that options are only passed once.
option_checking = ('option-checking' not in known_args
or known_args['option-checking'][-1][1])
option_checking = (
"option-checking" not in known_args or known_args["option-checking"][-1][1]
)
if option_checking:
if len(unknown_args) > 0:
err("Option '" + unknown_args[0] + "' is not recognized")
@ -272,18 +428,18 @@ def parse_args(args):
err("Option '{0}' needs a value ({0}=val)".format(need_value_args[0]))
global VERBOSE
VERBOSE = 'verbose-configure' in known_args
VERBOSE = "verbose-configure" in known_args
config = {}
set('build.configure-args', args, config)
set("build.configure-args", args, config)
apply_args(known_args, option_checking, config)
return parse_example_config(known_args, config)
def build(known_args):
if 'build' in known_args:
return known_args['build'][-1][1]
if "build" in known_args:
return known_args["build"][-1][1]
return bootstrap.default_build_triple(verbose=False)
@ -291,7 +447,7 @@ def set(key, value, config):
if isinstance(value, list):
# Remove empty values, which value.split(',') tends to generate and
# replace single quotes for double quotes to ensure correct parsing.
value = [v.replace('\'', '"') for v in value if v]
value = [v.replace("'", '"') for v in value if v]
s = "{:20} := {}".format(key, value)
if len(s) < 70 or VERBOSE:
@ -310,7 +466,7 @@ def set(key, value, config):
for i, part in enumerate(parts):
if i == len(parts) - 1:
if is_value_list(part) and isinstance(value, str):
value = value.split(',')
value = value.split(",")
arr[part] = value
else:
if part not in arr:
@ -321,9 +477,9 @@ def set(key, value, config):
def apply_args(known_args, option_checking, config):
for key in known_args:
# The `set` option is special and can be passed a bunch of times
if key == 'set':
if key == "set":
for _option, value in known_args[key]:
keyval = value.split('=', 1)
keyval = value.split("=", 1)
if len(keyval) == 1 or keyval[1] == "true":
value = True
elif keyval[1] == "false":
@ -348,50 +504,55 @@ def apply_args(known_args, option_checking, config):
# that here.
build_triple = build(known_args)
if option.name == 'sccache':
set('llvm.ccache', 'sccache', config)
elif option.name == 'local-rust':
for path in os.environ['PATH'].split(os.pathsep):
if os.path.exists(path + '/rustc'):
set('build.rustc', path + '/rustc', config)
if option.name == "sccache":
set("llvm.ccache", "sccache", config)
elif option.name == "local-rust":
for path in os.environ["PATH"].split(os.pathsep):
if os.path.exists(path + "/rustc"):
set("build.rustc", path + "/rustc", config)
break
for path in os.environ['PATH'].split(os.pathsep):
if os.path.exists(path + '/cargo'):
set('build.cargo', path + '/cargo', config)
for path in os.environ["PATH"].split(os.pathsep):
if os.path.exists(path + "/cargo"):
set("build.cargo", path + "/cargo", config)
break
elif option.name == 'local-rust-root':
set('build.rustc', value + '/bin/rustc', config)
set('build.cargo', value + '/bin/cargo', config)
elif option.name == 'llvm-root':
set('target.{}.llvm-config'.format(build_triple), value + '/bin/llvm-config', config)
elif option.name == 'llvm-config':
set('target.{}.llvm-config'.format(build_triple), value, config)
elif option.name == 'llvm-filecheck':
set('target.{}.llvm-filecheck'.format(build_triple), value, config)
elif option.name == 'tools':
set('build.tools', value.split(','), config)
elif option.name == 'bootstrap-cache-path':
set('build.bootstrap-cache-path', value, config)
elif option.name == 'codegen-backends':
set('rust.codegen-backends', value.split(','), config)
elif option.name == 'host':
set('build.host', value.split(','), config)
elif option.name == 'target':
set('build.target', value.split(','), config)
elif option.name == 'full-tools':
set('rust.codegen-backends', ['llvm'], config)
set('rust.lld', True, config)
set('rust.llvm-tools', True, config)
set('rust.llvm-bitcode-linker', True, config)
set('build.extended', True, config)
elif option.name in ['option-checking', 'verbose-configure']:
elif option.name == "local-rust-root":
set("build.rustc", value + "/bin/rustc", config)
set("build.cargo", value + "/bin/cargo", config)
elif option.name == "llvm-root":
set(
"target.{}.llvm-config".format(build_triple),
value + "/bin/llvm-config",
config,
)
elif option.name == "llvm-config":
set("target.{}.llvm-config".format(build_triple), value, config)
elif option.name == "llvm-filecheck":
set("target.{}.llvm-filecheck".format(build_triple), value, config)
elif option.name == "tools":
set("build.tools", value.split(","), config)
elif option.name == "bootstrap-cache-path":
set("build.bootstrap-cache-path", value, config)
elif option.name == "codegen-backends":
set("rust.codegen-backends", value.split(","), config)
elif option.name == "host":
set("build.host", value.split(","), config)
elif option.name == "target":
set("build.target", value.split(","), config)
elif option.name == "full-tools":
set("rust.codegen-backends", ["llvm"], config)
set("rust.lld", True, config)
set("rust.llvm-tools", True, config)
set("rust.llvm-bitcode-linker", True, config)
set("build.extended", True, config)
elif option.name in ["option-checking", "verbose-configure"]:
# this was handled above
pass
elif option.name == 'dist-compression-formats':
set('dist.compression-formats', value.split(','), config)
elif option.name == "dist-compression-formats":
set("dist.compression-formats", value.split(","), config)
else:
raise RuntimeError("unhandled option {}".format(option.name))
# "Parse" the `config.example.toml` file into the various sections, and we'll
# use this as a template of a `config.toml` to write out which preserves
# all the various comments and whatnot.
@ -406,20 +567,22 @@ def parse_example_config(known_args, config):
targets = {}
top_level_keys = []
with open(rust_dir + '/config.example.toml') as example_config:
with open(rust_dir + "/config.example.toml") as example_config:
example_lines = example_config.read().split("\n")
for line in example_lines:
if cur_section is None:
if line.count('=') == 1:
top_level_key = line.split('=')[0]
top_level_key = top_level_key.strip(' #')
if line.count("=") == 1:
top_level_key = line.split("=")[0]
top_level_key = top_level_key.strip(" #")
top_level_keys.append(top_level_key)
if line.startswith('['):
if line.startswith("["):
cur_section = line[1:-1]
if cur_section.startswith('target'):
cur_section = 'target'
elif '.' in cur_section:
raise RuntimeError("don't know how to deal with section: {}".format(cur_section))
if cur_section.startswith("target"):
cur_section = "target"
elif "." in cur_section:
raise RuntimeError(
"don't know how to deal with section: {}".format(cur_section)
)
sections[cur_section] = [line]
section_order.append(cur_section)
else:
@ -428,22 +591,25 @@ def parse_example_config(known_args, config):
# Fill out the `targets` array by giving all configured targets a copy of the
# `target` section we just loaded from the example config
configured_targets = [build(known_args)]
if 'build' in config:
if 'host' in config['build']:
configured_targets += config['build']['host']
if 'target' in config['build']:
configured_targets += config['build']['target']
if 'target' in config:
for target in config['target']:
if "build" in config:
if "host" in config["build"]:
configured_targets += config["build"]["host"]
if "target" in config["build"]:
configured_targets += config["build"]["target"]
if "target" in config:
for target in config["target"]:
configured_targets.append(target)
for target in configured_targets:
targets[target] = sections['target'][:]
targets[target] = sections["target"][:]
# For `.` to be valid TOML, it needs to be quoted. But `bootstrap.py` doesn't use a proper TOML parser and fails to parse the target.
# Avoid using quotes unless it's necessary.
targets[target][0] = targets[target][0].replace("x86_64-unknown-linux-gnu", "'{}'".format(target) if "." in target else target)
targets[target][0] = targets[target][0].replace(
"x86_64-unknown-linux-gnu",
"'{}'".format(target) if "." in target else target,
)
if 'profile' not in config:
set('profile', 'dist', config)
if "profile" not in config:
set("profile", "dist", config)
configure_file(sections, top_level_keys, targets, config)
return section_order, sections, targets
@ -467,7 +633,7 @@ def to_toml(value):
else:
return "false"
elif isinstance(value, list):
return '[' + ', '.join(map(to_toml, value)) + ']'
return "[" + ", ".join(map(to_toml, value)) + "]"
elif isinstance(value, str):
# Don't put quotes around numeric values
if is_number(value):
@ -475,9 +641,18 @@ def to_toml(value):
else:
return "'" + value + "'"
elif isinstance(value, dict):
return "{" + ", ".join(map(lambda a: "{} = {}".format(to_toml(a[0]), to_toml(a[1])), value.items())) + "}"
return (
"{"
+ ", ".join(
map(
lambda a: "{} = {}".format(to_toml(a[0]), to_toml(a[1])),
value.items(),
)
)
+ "}"
)
else:
raise RuntimeError('no toml')
raise RuntimeError("no toml")
def configure_section(lines, config):
@ -485,7 +660,7 @@ def configure_section(lines, config):
value = config[key]
found = False
for i, line in enumerate(lines):
if not line.startswith('#' + key + ' = '):
if not line.startswith("#" + key + " = "):
continue
found = True
lines[i] = "{} = {}".format(key, to_toml(value))
@ -501,7 +676,9 @@ def configure_section(lines, config):
def configure_top_level_key(lines, top_level_key, value):
for i, line in enumerate(lines):
if line.startswith('#' + top_level_key + ' = ') or line.startswith(top_level_key + ' = '):
if line.startswith("#" + top_level_key + " = ") or line.startswith(
top_level_key + " = "
):
lines[i] = "{} = {}".format(top_level_key, to_toml(value))
return
@ -512,11 +689,13 @@ def configure_top_level_key(lines, top_level_key, value):
def configure_file(sections, top_level_keys, targets, config):
for section_key, section_config in config.items():
if section_key not in sections and section_key not in top_level_keys:
raise RuntimeError("config key {} not in sections or top_level_keys".format(section_key))
raise RuntimeError(
"config key {} not in sections or top_level_keys".format(section_key)
)
if section_key in top_level_keys:
configure_top_level_key(sections[None], section_key, section_config)
elif section_key == 'target':
elif section_key == "target":
for target in section_config:
configure_section(targets[target], section_config[target])
else:
@ -536,18 +715,19 @@ def write_uncommented(target, f):
block = []
is_comment = True
continue
is_comment = is_comment and line.startswith('#')
is_comment = is_comment and line.startswith("#")
return f
def write_config_toml(writer, section_order, targets, sections):
for section in section_order:
if section == 'target':
if section == "target":
for target in targets:
writer = write_uncommented(targets[target], writer)
else:
writer = write_uncommented(sections[section], writer)
def quit_if_file_exists(file):
if os.path.isfile(file):
msg = "Existing '{}' detected. Exiting".format(file)
@ -559,9 +739,10 @@ def quit_if_file_exists(file):
err(msg)
if __name__ == "__main__":
# If 'config.toml' already exists, exit the script at this point
quit_if_file_exists('config.toml')
quit_if_file_exists("config.toml")
if "GITHUB_ACTIONS" in os.environ:
print("::group::Configure the build")
@ -575,13 +756,13 @@ if __name__ == "__main__":
# order that we read it in.
p("")
p("writing `config.toml` in current directory")
with bootstrap.output('config.toml') as f:
with bootstrap.output("config.toml") as f:
write_config_toml(f, section_order, targets, sections)
with bootstrap.output('Makefile') as f:
contents = os.path.join(rust_dir, 'src', 'bootstrap', 'mk', 'Makefile.in')
with bootstrap.output("Makefile") as f:
contents = os.path.join(rust_dir, "src", "bootstrap", "mk", "Makefile.in")
contents = open(contents).read()
contents = contents.replace("$(CFG_SRC_DIR)", rust_dir + '/')
contents = contents.replace("$(CFG_SRC_DIR)", rust_dir + "/")
contents = contents.replace("$(CFG_PYTHON)", sys.executable)
f.write(contents)

View file

@ -108,11 +108,13 @@ ci-msvc: ci-msvc-py ci-msvc-ps1
## MingW native builders
# test both x and bootstrap entrypoints
# Set of tests that should represent half of the time of the test suite.
# Used to split tests across multiple CI runners.
# Test both x and bootstrap entrypoints.
ci-mingw-x:
$(Q)$(CFG_SRC_DIR)/x test --stage 2 tidy
$(Q)$(CFG_SRC_DIR)/x test --stage 2 --skip=compiler --skip=src
ci-mingw-bootstrap:
$(Q)$(BOOTSTRAP) test --stage 2 --skip tidy
$(Q)$(BOOTSTRAP) test --stage 2 --skip=tests --skip=coverage-map --skip=coverage-run --skip=library --skip=tidyselftest
ci-mingw: ci-mingw-x ci-mingw-bootstrap
.PHONY: dist

View file

@ -48,9 +48,9 @@ fn main() {
err => {
drop(err);
if let Ok(pid) = pid {
println!("WARNING: build directory locked by process {pid}, waiting for lock");
eprintln!("WARNING: build directory locked by process {pid}, waiting for lock");
} else {
println!("WARNING: build directory locked, waiting for lock");
eprintln!("WARNING: build directory locked, waiting for lock");
}
let mut lock = t!(build_lock.write());
t!(lock.write(process::id().to_string().as_ref()));
@ -70,13 +70,13 @@ fn main() {
// changelog warning, not the `x.py setup` message.
let suggest_setup = config.config.is_none() && !matches!(config.cmd, Subcommand::Setup { .. });
if suggest_setup {
println!("WARNING: you have not made a `config.toml`");
println!(
eprintln!("WARNING: you have not made a `config.toml`");
eprintln!(
"HELP: consider running `./x.py setup` or copying `config.example.toml` by running \
`cp config.example.toml config.toml`"
);
} else if let Some(suggestion) = &changelog_suggestion {
println!("{suggestion}");
eprintln!("{suggestion}");
}
let pre_commit = config.src.join(".git").join("hooks").join("pre-commit");
@ -86,30 +86,30 @@ fn main() {
Build::new(config).build();
if suggest_setup {
println!("WARNING: you have not made a `config.toml`");
println!(
eprintln!("WARNING: you have not made a `config.toml`");
eprintln!(
"HELP: consider running `./x.py setup` or copying `config.example.toml` by running \
`cp config.example.toml config.toml`"
);
} else if let Some(suggestion) = &changelog_suggestion {
println!("{suggestion}");
eprintln!("{suggestion}");
}
// Give a warning if the pre-commit script is in pre-commit and not pre-push.
// HACK: Since the commit script uses hard links, we can't actually tell if it was installed by x.py setup or not.
// We could see if it's identical to src/etc/pre-push.sh, but pre-push may have been modified in the meantime.
// Instead, look for this comment, which is almost certainly not in any custom hook.
if fs::read_to_string(pre_commit).map_or(false, |contents| {
if fs::read_to_string(pre_commit).is_ok_and(|contents| {
contents.contains("https://github.com/rust-lang/rust/issues/77620#issuecomment-705144570")
}) {
println!(
eprintln!(
"WARNING: You have the pre-push script installed to .git/hooks/pre-commit. \
Consider moving it to .git/hooks/pre-push instead, which runs less often."
);
}
if suggest_setup || changelog_suggestion.is_some() {
println!("NOTE: this message was printed twice to make it more likely to be seen");
eprintln!("NOTE: this message was printed twice to make it more likely to be seen");
}
if dump_bootstrap_shims {

View file

@ -306,7 +306,7 @@ fn main() {
// should run on success, after this block.
}
if verbose > 0 {
println!("\nDid not run successfully: {status}\n{cmd:?}\n-------------");
eprintln!("\nDid not run successfully: {status}\n{cmd:?}\n-------------");
}
if let Some(mut on_fail) = on_fail {

View file

@ -287,7 +287,7 @@ impl Step for CodegenBackend {
fn run(self, builder: &Builder<'_>) {
// FIXME: remove once https://github.com/rust-lang/rust/issues/112393 is resolved
if builder.build.config.vendor && self.backend == "gcc" {
println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
eprintln!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
return;
}

View file

@ -203,10 +203,8 @@ fn rm_rf(path: &Path) {
do_op(path, "remove dir", |p| match fs::remove_dir(p) {
// Check for dir not empty on Windows
// FIXME: Once `ErrorKind::DirectoryNotEmpty` is stabilized,
// match on `e.kind()` instead.
#[cfg(windows)]
Err(e) if e.raw_os_error() == Some(145) => Ok(()),
Err(e) if e.kind() == ErrorKind::DirectoryNotEmpty => Ok(()),
r => r,
});
}

View file

@ -330,7 +330,7 @@ fn copy_third_party_objects(
if target == "x86_64-fortanix-unknown-sgx"
|| builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree
&& (target.contains("linux") || target.contains("fuchsia"))
&& (target.contains("linux") || target.contains("fuchsia") || target.contains("aix"))
{
let libunwind_path =
copy_llvm_libunwind(builder, target, &builder.sysroot_target_libdir(*compiler, target));
@ -1611,7 +1611,7 @@ impl Step for Sysroot {
let sysroot = sysroot_dir(compiler.stage);
builder
.verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
.verbose(|| eprintln!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
let _ = fs::remove_dir_all(&sysroot);
t!(fs::create_dir_all(&sysroot));
@ -1655,7 +1655,7 @@ impl Step for Sysroot {
let mut add_filtered_files = |suffix, contents| {
for path in contents {
let path = Path::new(&path);
if path.parent().map_or(false, |parent| parent.ends_with(suffix)) {
if path.parent().is_some_and(|parent| parent.ends_with(suffix)) {
filtered_files.push(path.file_name().unwrap().to_owned());
}
}
@ -1681,7 +1681,7 @@ impl Step for Sysroot {
return true;
}
if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
builder.verbose_than(1, || println!("ignoring {}", path.display()));
builder.verbose_than(1, || eprintln!("ignoring {}", path.display()));
false
} else {
true
@ -2240,7 +2240,7 @@ pub fn stream_cargo(
cargo.arg(arg);
}
builder.verbose(|| println!("running: {cargo:?}"));
builder.verbose(|| eprintln!("running: {cargo:?}"));
if builder.config.dry_run() {
return true;
@ -2266,7 +2266,7 @@ pub fn stream_cargo(
cb(msg)
}
// If this was informational, just print it out and continue
Err(_) => println!("{line}"),
Err(_) => eprintln!("{line}"),
}
}

View file

@ -549,24 +549,24 @@ impl Step for DebuggerScripts {
cp_debugger_script("natvis/liballoc.natvis");
cp_debugger_script("natvis/libcore.natvis");
cp_debugger_script("natvis/libstd.natvis");
} else {
cp_debugger_script("rust_types.py");
// gdb debugger scripts
builder.install(&builder.src.join("src/etc/rust-gdb"), &sysroot.join("bin"), 0o755);
builder.install(&builder.src.join("src/etc/rust-gdbgui"), &sysroot.join("bin"), 0o755);
cp_debugger_script("gdb_load_rust_pretty_printers.py");
cp_debugger_script("gdb_lookup.py");
cp_debugger_script("gdb_providers.py");
// lldb debugger scripts
builder.install(&builder.src.join("src/etc/rust-lldb"), &sysroot.join("bin"), 0o755);
cp_debugger_script("lldb_lookup.py");
cp_debugger_script("lldb_providers.py");
cp_debugger_script("lldb_commands")
}
cp_debugger_script("rust_types.py");
// gdb debugger scripts
builder.install(&builder.src.join("src/etc/rust-gdb"), &sysroot.join("bin"), 0o755);
builder.install(&builder.src.join("src/etc/rust-gdbgui"), &sysroot.join("bin"), 0o755);
cp_debugger_script("gdb_load_rust_pretty_printers.py");
cp_debugger_script("gdb_lookup.py");
cp_debugger_script("gdb_providers.py");
// lldb debugger scripts
builder.install(&builder.src.join("src/etc/rust-lldb"), &sysroot.join("bin"), 0o755);
cp_debugger_script("lldb_lookup.py");
cp_debugger_script("lldb_providers.py");
cp_debugger_script("lldb_commands")
}
}
@ -2080,7 +2080,7 @@ fn maybe_install_llvm(
{
let mut cmd = command(llvm_config);
cmd.arg("--libfiles");
builder.verbose(|| println!("running {cmd:?}"));
builder.verbose(|| eprintln!("running {cmd:?}"));
let files = cmd.run_capture_stdout(builder).stdout();
let build_llvm_out = &builder.llvm_out(builder.config.build);
let target_llvm_out = &builder.llvm_out(target);

View file

@ -56,10 +56,7 @@ fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl F
fn get_rustfmt_version(build: &Builder<'_>) -> Option<(String, PathBuf)> {
let stamp_file = build.out.join("rustfmt.stamp");
let mut cmd = command(match build.initial_rustfmt() {
Some(p) => p,
None => return None,
});
let mut cmd = command(build.initial_rustfmt()?);
cmd.arg("--version");
let output = cmd.allow_failure().run_capture(build);
@ -110,10 +107,10 @@ fn print_paths(verb: &str, adjective: Option<&str>, paths: &[String]) {
if let Some(adjective) = adjective { format!("{adjective} ") } else { String::new() };
if len <= 10 {
for path in paths {
println!("fmt: {verb} {adjective}file {path}");
eprintln!("fmt: {verb} {adjective}file {path}");
}
} else {
println!("fmt: {verb} {len} {adjective}files");
eprintln!("fmt: {verb} {len} {adjective}files");
}
}
@ -202,7 +199,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
match get_modified_rs_files(build) {
Ok(Some(files)) => {
if files.is_empty() {
println!("fmt info: No modified files detected for formatting.");
eprintln!("fmt info: No modified files detected for formatting.");
return;
}
@ -279,7 +276,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
Box::new(move |entry| {
let cwd = std::env::current_dir();
let entry = t!(entry);
if entry.file_type().map_or(false, |t| t.is_file()) {
if entry.file_type().is_some_and(|t| t.is_file()) {
formatted_paths_ref.lock().unwrap().push({
// `into_path` produces an absolute path. Try to strip `cwd` to get a shorter
// relative path.

View file

@ -21,9 +21,9 @@ const SHELL: &str = "sh";
/// We have to run a few shell scripts, which choke quite a bit on both `\`
/// characters and on `C:\` paths, so normalize both of them away.
fn sanitize_sh(path: &Path) -> String {
fn sanitize_sh(path: &Path, is_cygwin: bool) -> String {
let path = path.to_str().unwrap().replace('\\', "/");
return change_drive(unc_to_lfs(&path)).unwrap_or(path);
return if is_cygwin { path } else { change_drive(unc_to_lfs(&path)).unwrap_or(path) };
fn unc_to_lfs(s: &str) -> &str {
s.strip_prefix("//?/").unwrap_or(s)
@ -71,6 +71,7 @@ fn install_sh(
let prefix = default_path(&builder.config.prefix, "/usr/local");
let sysconfdir = prefix.join(default_path(&builder.config.sysconfdir, "/etc"));
let destdir_env = env::var_os("DESTDIR").map(PathBuf::from);
let is_cygwin = builder.config.build.is_cygwin();
// Sanity checks on the write access of user.
//
@ -103,14 +104,14 @@ fn install_sh(
let mut cmd = command(SHELL);
cmd.current_dir(&empty_dir)
.arg(sanitize_sh(&tarball.decompressed_output().join("install.sh")))
.arg(format!("--prefix={}", prepare_dir(&destdir_env, prefix)))
.arg(format!("--sysconfdir={}", prepare_dir(&destdir_env, sysconfdir)))
.arg(format!("--datadir={}", prepare_dir(&destdir_env, datadir)))
.arg(format!("--docdir={}", prepare_dir(&destdir_env, docdir)))
.arg(format!("--bindir={}", prepare_dir(&destdir_env, bindir)))
.arg(format!("--libdir={}", prepare_dir(&destdir_env, libdir)))
.arg(format!("--mandir={}", prepare_dir(&destdir_env, mandir)))
.arg(sanitize_sh(&tarball.decompressed_output().join("install.sh"), is_cygwin))
.arg(format!("--prefix={}", prepare_dir(&destdir_env, prefix, is_cygwin)))
.arg(format!("--sysconfdir={}", prepare_dir(&destdir_env, sysconfdir, is_cygwin)))
.arg(format!("--datadir={}", prepare_dir(&destdir_env, datadir, is_cygwin)))
.arg(format!("--docdir={}", prepare_dir(&destdir_env, docdir, is_cygwin)))
.arg(format!("--bindir={}", prepare_dir(&destdir_env, bindir, is_cygwin)))
.arg(format!("--libdir={}", prepare_dir(&destdir_env, libdir, is_cygwin)))
.arg(format!("--mandir={}", prepare_dir(&destdir_env, mandir, is_cygwin)))
.arg("--disable-ldconfig");
cmd.run(builder);
t!(fs::remove_dir_all(&empty_dir));
@ -120,7 +121,7 @@ fn default_path(config: &Option<PathBuf>, default: &str) -> PathBuf {
config.as_ref().cloned().unwrap_or_else(|| PathBuf::from(default))
}
fn prepare_dir(destdir_env: &Option<PathBuf>, mut path: PathBuf) -> String {
fn prepare_dir(destdir_env: &Option<PathBuf>, mut path: PathBuf, is_cygwin: bool) -> String {
// The DESTDIR environment variable is a standard way to install software in a subdirectory
// while keeping the original directory structure, even if the prefix or other directories
// contain absolute paths.
@ -146,7 +147,7 @@ fn prepare_dir(destdir_env: &Option<PathBuf>, mut path: PathBuf) -> String {
assert!(path.is_absolute(), "could not make the path relative");
}
sanitize_sh(&path)
sanitize_sh(&path, is_cygwin)
}
macro_rules! install {

View file

@ -134,7 +134,7 @@ impl Step for Profile {
t!(fs::remove_file(path));
}
_ => {
println!("Exiting.");
eprintln!("Exiting.");
crate::exit!(1);
}
}
@ -184,15 +184,15 @@ pub fn setup(config: &Config, profile: Profile) {
Profile::Dist => &["dist", "build"],
};
println!();
eprintln!();
println!("To get started, try one of the following commands:");
eprintln!("To get started, try one of the following commands:");
for cmd in suggestions {
println!("- `x.py {cmd}`");
eprintln!("- `x.py {cmd}`");
}
if profile != Profile::Dist {
println!(
eprintln!(
"For more suggestions, see https://rustc-dev-guide.rust-lang.org/building/suggested.html"
);
}
@ -224,7 +224,7 @@ fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) {
t!(fs::write(path, settings));
let include_path = profile.include_path(&config.src);
println!("`x.py` will now use the configuration at {}", include_path.display());
eprintln!("`x.py` will now use the configuration at {}", include_path.display());
}
/// Creates a toolchain link for stage1 using `rustup`
@ -256,7 +256,7 @@ impl Step for Link {
}
if !rustup_installed(builder) {
println!("WARNING: `rustup` is not installed; Skipping `stage1` toolchain linking.");
eprintln!("WARNING: `rustup` is not installed; Skipping `stage1` toolchain linking.");
return;
}
@ -296,7 +296,7 @@ fn attempt_toolchain_link(builder: &Builder<'_>, stage_path: &str) {
}
if try_link_toolchain(builder, stage_path) {
println!(
eprintln!(
"Added `stage1` rustup toolchain; try `cargo +stage1 build` on a separate rust project to run a newly-built toolchain"
);
} else {
@ -321,14 +321,14 @@ fn toolchain_is_linked(builder: &Builder<'_>) -> bool {
return false;
}
// The toolchain has already been linked.
println!(
eprintln!(
"`stage1` toolchain already linked; not attempting to link `stage1` toolchain"
);
}
None => {
// In this case, we don't know if the `stage1` toolchain has been linked;
// but `rustup` failed, so let's not go any further.
println!(
eprintln!(
"`rustup` failed to list current toolchains; not attempting to link `stage1` toolchain"
);
}
@ -389,12 +389,12 @@ pub fn interactive_path() -> io::Result<Profile> {
input.parse()
}
println!("Welcome to the Rust project! What do you want to do with x.py?");
eprintln!("Welcome to the Rust project! What do you want to do with x.py?");
for ((letter, _), profile) in abbrev_all() {
println!("{}) {}: {}", letter, profile, profile.purpose());
eprintln!("{}) {}: {}", letter, profile, profile.purpose());
}
let template = loop {
print!(
eprint!(
"Please choose one ({}): ",
abbrev_all().map(|((l, _), _)| l).collect::<Vec<_>>().join("/")
);
@ -428,7 +428,7 @@ enum PromptResult {
fn prompt_user(prompt: &str) -> io::Result<Option<PromptResult>> {
let mut input = String::new();
loop {
print!("{prompt} ");
eprint!("{prompt} ");
io::stdout().flush()?;
input.clear();
io::stdin().read_line(&mut input)?;
@ -452,24 +452,26 @@ pub struct Hook;
impl Step for Hook {
type Output = ();
const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.alias("hook")
}
fn make_run(run: RunConfig<'_>) {
if run.builder.config.dry_run() {
return;
}
if let [cmd] = &run.paths[..] {
if cmd.assert_single_path().path.as_path().as_os_str() == "hook" {
run.builder.ensure(Hook);
}
}
}
fn run(self, builder: &Builder<'_>) -> Self::Output {
let config = &builder.config;
if config.dry_run() {
if config.dry_run() || !config.rust_info.is_managed_git_subrepository() {
return;
}
t!(install_git_hook_maybe(builder, config));
}
}
@ -488,7 +490,7 @@ fn install_git_hook_maybe(builder: &Builder<'_>, config: &Config) -> io::Result<
return Ok(());
}
println!(
eprintln!(
"\nRust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality.
If you'd like, x.py can install a git hook for you that will automatically run `test tidy` before
pushing your code to ensure your code is up to par. If you decide later that this behavior is
@ -496,7 +498,7 @@ undesirable, simply delete the `pre-push` file from .git/hooks."
);
if prompt_user("Would you like to install the git hook?: [y/N]")? != Some(PromptResult::Yes) {
println!("Ok, skipping installation!");
eprintln!("Ok, skipping installation!");
return Ok(());
}
if !hooks_dir.exists() {
@ -513,7 +515,7 @@ undesirable, simply delete the `pre-push` file from .git/hooks."
);
return Err(e);
}
Ok(_) => println!("Linked `src/etc/pre-push.sh` to `.git/hooks/pre-push`"),
Ok(_) => eprintln!("Linked `src/etc/pre-push.sh` to `.git/hooks/pre-push`"),
};
Ok(())
}
@ -539,7 +541,7 @@ Select which editor you would like to set up [default: None]: ";
let mut input = String::new();
loop {
print!("{}", prompt_str);
eprint!("{}", prompt_str);
io::stdout().flush()?;
input.clear();
io::stdin().read_line(&mut input)?;
@ -572,6 +574,7 @@ Select which editor you would like to set up [default: None]: ";
"828666b021d837a33e78d870b56d34c88a5e2c85de58b693607ec574f0c27000",
"811fb3b063c739d261fd8590dd30242e117908f5a095d594fa04585daa18ec4d",
"4eecb58a2168b252077369da446c30ed0e658301efe69691979d1ef0443928f4",
"c394386e6133bbf29ffd32c8af0bb3d4aac354cba9ee051f29612aa9350f8f8d",
],
EditorKind::Emacs => vec![
"51068d4747a13732440d1a8b8f432603badb1864fa431d83d0fd4f8fa57039e0",
@ -653,7 +656,7 @@ impl Step for Editor {
if let Some(editor_kind) = editor_kind {
while !t!(create_editor_settings_maybe(config, editor_kind.clone())) {}
} else {
println!("Ok, skipping editor setup!");
eprintln!("Ok, skipping editor setup!");
}
}
Err(e) => eprintln!("Could not determine the editor: {e}"),
@ -686,7 +689,7 @@ fn create_editor_settings_maybe(config: &Config, editor: EditorKind) -> io::Resu
mismatched_settings = Some(false);
}
}
println!(
eprintln!(
"\nx.py can automatically install the recommended `{settings_filename}` file for rustc development"
);
@ -705,7 +708,7 @@ fn create_editor_settings_maybe(config: &Config, editor: EditorKind) -> io::Resu
Some(PromptResult::Yes) => true,
Some(PromptResult::Print) => false,
_ => {
println!("Ok, skipping settings!");
eprintln!("Ok, skipping settings!");
return Ok(true);
}
};
@ -732,9 +735,9 @@ fn create_editor_settings_maybe(config: &Config, editor: EditorKind) -> io::Resu
_ => "Created",
};
fs::write(&settings_path, editor.settings_template())?;
println!("{verb} `{}`", settings_filename);
eprintln!("{verb} `{}`", settings_filename);
} else {
println!("\n{}", editor.settings_template());
eprintln!("\n{}", editor.settings_template());
}
Ok(should_create)
}

View file

@ -66,6 +66,6 @@ pub fn suggest(builder: &Builder<'_>, run: bool) {
build.build();
}
} else {
println!("HELP: consider using the `--run` flag to automatically run suggested tests");
eprintln!("HELP: consider using the `--run` flag to automatically run suggested tests");
}
}

View file

@ -263,12 +263,16 @@ pub struct Cargo {
host: TargetSelection,
}
impl Cargo {
const CRATE_PATH: &str = "src/tools/cargo";
}
impl Step for Cargo {
type Output = ();
const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.path("src/tools/cargo")
run.path(Self::CRATE_PATH)
}
fn make_run(run: RunConfig<'_>) {
@ -286,7 +290,7 @@ impl Step for Cargo {
Mode::ToolRustc,
self.host,
Kind::Test,
"src/tools/cargo",
Self::CRATE_PATH,
SourceType::Submodule,
&[],
);
@ -301,6 +305,10 @@ impl Step for Cargo {
// those features won't be able to land.
cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
cargo.env("PATH", path_for_cargo(builder, compiler));
// Cargo's test suite uses `CARGO_RUSTC_CURRENT_DIR` to determine the path that `file!` is
// relative to. Cargo no longer sets this env var, so we have to do that. This has to be the
// same value as `-Zroot-dir`.
cargo.env("CARGO_RUSTC_CURRENT_DIR", builder.src.display().to_string());
#[cfg(feature = "build-metrics")]
builder.metrics.begin_test_suite(
@ -463,11 +471,11 @@ impl Miri {
// We re-use the `cargo` from above.
cargo.arg("--print-sysroot");
builder.verbose(|| println!("running: {cargo:?}"));
builder.verbose(|| eprintln!("running: {cargo:?}"));
let stdout = cargo.run_capture_stdout(builder).stdout();
// Output is "<sysroot>\n".
let sysroot = stdout.trim_end();
builder.verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
builder.verbose(|| eprintln!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
PathBuf::from(sysroot)
}
}
@ -1062,23 +1070,33 @@ impl Step for Tidy {
}
if builder.config.channel == "dev" || builder.config.channel == "nightly" {
builder.info("fmt check");
if builder.initial_rustfmt().is_none() {
let inferred_rustfmt_dir = builder.initial_rustc.parent().unwrap();
eprintln!(
"\
if !builder.config.json_output {
builder.info("fmt check");
if builder.initial_rustfmt().is_none() {
let inferred_rustfmt_dir = builder.initial_sysroot.join("bin");
eprintln!(
"\
ERROR: no `rustfmt` binary found in {PATH}
INFO: `rust.channel` is currently set to \"{CHAN}\"
HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `config.toml` file
HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`",
PATH = inferred_rustfmt_dir.display(),
CHAN = builder.config.channel,
PATH = inferred_rustfmt_dir.display(),
CHAN = builder.config.channel,
);
crate::exit!(1);
}
let all = false;
crate::core::build_steps::format::format(
builder,
!builder.config.cmd.bless(),
all,
&[],
);
} else {
eprintln!(
"WARNING: `--json-output` is not supported on rustfmt, formatting will be skipped"
);
crate::exit!(1);
}
let all = false;
crate::core::build_steps::format::format(builder, !builder.config.cmd.bless(), all, &[
]);
}
builder.info("tidy check");
@ -2470,7 +2488,7 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) ->
}
}
builder.verbose(|| println!("doc tests for: {}", markdown.display()));
builder.verbose(|| eprintln!("doc tests for: {}", markdown.display()));
let mut cmd = builder.rustdoc_cmd(compiler);
builder.add_rust_test_threads(&mut cmd);
// allow for unstable options such as new editions
@ -2616,6 +2634,11 @@ fn prepare_cargo_test(
if builder.kind == Kind::Test && !builder.fail_fast {
cargo.arg("--no-fail-fast");
}
if builder.config.json_output {
cargo.arg("--message-format=json");
}
match builder.doc_tests {
DocTests::Only => {
cargo.arg("--doc");
@ -2748,6 +2771,10 @@ impl Step for Crate {
// `lib.rs` file, and a `lib.miri.rs` file exists in the same folder, we build that
// instead. But crucially we only do that for the library, not the test builds.
cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
// std needs to be built with `-Zforce-unstable-if-unmarked`. For some reason the builder
// does not set this directly, but relies on the rustc wrapper to set it, and we are not using
// the wrapper -- hence we have to set it ourselves.
cargo.rustflag("-Zforce-unstable-if-unmarked");
cargo
} else {
// Also prepare a sysroot for the target.

View file

@ -523,7 +523,7 @@ impl Builder<'_> {
let sysroot_str = sysroot.as_os_str().to_str().expect("sysroot should be UTF-8");
if self.is_verbose() && !matches!(self.config.dry_run, DryRun::SelfCheck) {
println!("using sysroot {sysroot_str}");
eprintln!("using sysroot {sysroot_str}");
}
let mut rustflags = Rustflags::new(target);
@ -703,6 +703,9 @@ impl Builder<'_> {
cargo.arg("-j").arg(self.jobs().to_string());
// Make cargo emit diagnostics relative to the rustc src dir.
cargo.arg(format!("-Zroot-dir={}", self.src.display()));
// FIXME: Temporary fix for https://github.com/rust-lang/cargo/issues/3005
// Force cargo to output binaries with disambiguating hashes in the name
let mut metadata = if compiler.stage == 0 {
@ -1030,6 +1033,15 @@ impl Builder<'_> {
if mode == Mode::Rustc {
rustflags.arg("-Wrustc::internal");
// cfg(bootstrap) - remove this check when lint is in bootstrap compiler
if stage != 0 {
// Lint is allow by default so downstream tools don't get a lit
// they can do nothing about
// We shouldn't be preinterning symbols used by tests
if cmd_kind != Kind::Test {
rustflags.arg("-Drustc::symbol_intern_string_literal");
}
}
// FIXME(edition_2024): Change this to `-Wrust_2024_idioms` when all
// of the individual lints are satisfied.
rustflags.arg("-Wkeyword_idents_2024");

View file

@ -258,11 +258,11 @@ impl PathSet {
// internal use only
fn check(p: &TaskPath, needle: &Path, module: Kind) -> bool {
if let Some(p_kind) = &p.kind {
p.path.ends_with(needle) && *p_kind == module
} else {
p.path.ends_with(needle)
}
let check_path = || {
// This order is important for retro-compatibility, as `starts_with` was introduced later.
p.path.ends_with(needle) || p.path.starts_with(needle)
};
if let Some(p_kind) = &p.kind { check_path() && *p_kind == module } else { check_path() }
}
/// Return all `TaskPath`s in `Self` that contain any of the `needles`, removing the
@ -392,14 +392,14 @@ impl StepDescription {
fn is_excluded(&self, builder: &Builder<'_>, pathset: &PathSet) -> bool {
if builder.config.skip.iter().any(|e| pathset.has(e, builder.kind)) {
if !matches!(builder.config.dry_run, DryRun::SelfCheck) {
println!("Skipping {pathset:?} because it is excluded");
eprintln!("Skipping {pathset:?} because it is excluded");
}
return true;
}
if !builder.config.skip.is_empty() && !matches!(builder.config.dry_run, DryRun::SelfCheck) {
builder.verbose(|| {
println!(
eprintln!(
"{:?} not skipped for {:?} -- not in {:?}",
pathset, self.name, builder.config.skip
)
@ -765,6 +765,54 @@ impl Kind {
}
}
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
struct Libdir {
compiler: Compiler,
target: TargetSelection,
}
impl Step for Libdir {
type Output = PathBuf;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.never()
}
fn run(self, builder: &Builder<'_>) -> PathBuf {
let relative_sysroot_libdir = builder.sysroot_libdir_relative(self.compiler);
let sysroot = builder.sysroot(self.compiler).join(relative_sysroot_libdir).join("rustlib");
if !builder.config.dry_run() {
// Avoid deleting the `rustlib/` directory we just copied (in `impl Step for
// Sysroot`).
if !builder.download_rustc() {
let sysroot_target_libdir = sysroot.join(self.target).join("lib");
builder.verbose(|| {
eprintln!(
"Removing sysroot {} to avoid caching bugs",
sysroot_target_libdir.display()
)
});
let _ = fs::remove_dir_all(&sysroot_target_libdir);
t!(fs::create_dir_all(&sysroot_target_libdir));
}
if self.compiler.stage == 0 {
// The stage 0 compiler for the build triple is always pre-built. Ensure that
// `libLLVM.so` ends up in the target libdir, so that ui-fulldeps tests can use
// it when run.
dist::maybe_install_llvm_target(
builder,
self.compiler.host,
&builder.sysroot(self.compiler),
);
}
}
sysroot
}
}
impl<'a> Builder<'a> {
fn get_step_descriptions(kind: Kind) -> Vec<StepDescription> {
macro_rules! describe {
@ -1165,56 +1213,13 @@ impl<'a> Builder<'a> {
/// Returns the bindir for a compiler's sysroot.
pub fn sysroot_target_bindir(&self, compiler: Compiler, target: TargetSelection) -> PathBuf {
self.sysroot_target_libdir(compiler, target).parent().unwrap().join("bin")
self.ensure(Libdir { compiler, target }).join(target).join("bin")
}
/// Returns the libdir where the standard library and other artifacts are
/// found for a compiler's sysroot.
pub fn sysroot_target_libdir(&self, compiler: Compiler, target: TargetSelection) -> PathBuf {
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
struct Libdir {
compiler: Compiler,
target: TargetSelection,
}
impl Step for Libdir {
type Output = PathBuf;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.never()
}
fn run(self, builder: &Builder<'_>) -> PathBuf {
let lib = builder.sysroot_libdir_relative(self.compiler);
let sysroot = builder
.sysroot(self.compiler)
.join(lib)
.join("rustlib")
.join(self.target)
.join("lib");
// Avoid deleting the rustlib/ directory we just copied
// (in `impl Step for Sysroot`).
if !builder.download_rustc() {
builder.verbose(|| {
println!("Removing sysroot {} to avoid caching bugs", sysroot.display())
});
let _ = fs::remove_dir_all(&sysroot);
t!(fs::create_dir_all(&sysroot));
}
if self.compiler.stage == 0 {
// The stage 0 compiler for the build triple is always pre-built.
// Ensure that `libLLVM.so` ends up in the target libdir, so that ui-fulldeps tests can use it when run.
dist::maybe_install_llvm_target(
builder,
self.compiler.host,
&builder.sysroot(self.compiler),
);
}
sysroot
}
}
self.ensure(Libdir { compiler, target })
self.ensure(Libdir { compiler, target }).join(target).join("lib")
}
pub fn sysroot_codegen_backends(&self, compiler: Compiler) -> PathBuf {
@ -1262,7 +1267,7 @@ impl<'a> Builder<'a> {
pub fn sysroot_libdir_relative(&self, compiler: Compiler) -> &Path {
match self.config.libdir_relative() {
Some(relative_libdir) if compiler.stage >= 1 => relative_libdir,
_ if compiler.stage == 0 => &self.build.initial_libdir,
_ if compiler.stage == 0 => &self.build.initial_relative_libdir,
_ => Path::new("lib"),
}
}
@ -1432,11 +1437,11 @@ impl<'a> Builder<'a> {
panic!("{}", out);
}
if let Some(out) = self.cache.get(&step) {
self.verbose_than(1, || println!("{}c {:?}", " ".repeat(stack.len()), step));
self.verbose_than(1, || eprintln!("{}c {:?}", " ".repeat(stack.len()), step));
return out;
}
self.verbose_than(1, || println!("{}> {:?}", " ".repeat(stack.len()), step));
self.verbose_than(1, || eprintln!("{}> {:?}", " ".repeat(stack.len()), step));
stack.push(Box::new(step.clone()));
}
@ -1457,7 +1462,7 @@ impl<'a> Builder<'a> {
let step_string = format!("{step:?}");
let brace_index = step_string.find('{').unwrap_or(0);
let type_string = type_name::<S>();
println!(
eprintln!(
"[TIMING] {} {} -- {}.{:03}",
&type_string.strip_prefix("bootstrap::").unwrap_or(type_string),
&step_string[brace_index..],
@ -1474,7 +1479,9 @@ impl<'a> Builder<'a> {
let cur_step = stack.pop().expect("step stack empty");
assert_eq!(cur_step.downcast_ref(), Some(&step));
}
self.verbose_than(1, || println!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step));
self.verbose_than(1, || {
eprintln!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step)
});
self.cache.put(step, out.clone());
out
}

View file

@ -738,3 +738,49 @@ mod dist {
]);
}
}
mod sysroot_target_dirs {
use super::{
Build, Builder, Compiler, TEST_TRIPLE_1, TEST_TRIPLE_2, TargetSelection, configure,
};
#[test]
fn test_sysroot_target_libdir() {
let build = Build::new(configure("build", &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]));
let builder = Builder::new(&build);
let target_triple_1 = TargetSelection::from_user(TEST_TRIPLE_1);
let compiler = Compiler { stage: 1, host: target_triple_1 };
let target_triple_2 = TargetSelection::from_user(TEST_TRIPLE_2);
let actual = builder.sysroot_target_libdir(compiler, target_triple_2);
assert_eq!(
builder
.sysroot(compiler)
.join(builder.sysroot_libdir_relative(compiler))
.join("rustlib")
.join(TEST_TRIPLE_2)
.join("lib"),
actual
);
}
#[test]
fn test_sysroot_target_bindir() {
let build = Build::new(configure("build", &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]));
let builder = Builder::new(&build);
let target_triple_1 = TargetSelection::from_user(TEST_TRIPLE_1);
let compiler = Compiler { stage: 1, host: target_triple_1 };
let target_triple_2 = TargetSelection::from_user(TEST_TRIPLE_2);
let actual = builder.sysroot_target_bindir(compiler, target_triple_2);
assert_eq!(
builder
.sysroot(compiler)
.join(builder.sysroot_libdir_relative(compiler))
.join("rustlib")
.join(TEST_TRIPLE_2)
.join("bin"),
actual
);
}
}

View file

@ -379,6 +379,7 @@ pub struct Config {
pub initial_cargo: PathBuf,
pub initial_rustc: PathBuf,
pub initial_cargo_clippy: Option<PathBuf>,
pub initial_sysroot: PathBuf,
#[cfg(not(test))]
initial_rustfmt: RefCell<RustfmtState>,
@ -564,6 +565,12 @@ impl TargetSelection {
self.ends_with("windows-gnu")
}
pub fn is_cygwin(&self) -> bool {
self.is_windows() &&
// ref. https://cygwin.com/pipermail/cygwin/2022-February/250802.html
env::var("OSTYPE").is_ok_and(|v| v.to_lowercase().contains("cygwin"))
}
/// Path to the file defining the custom target, if any.
pub fn filepath(&self) -> Option<&Path> {
self.file.as_ref().map(Path::new)
@ -1292,7 +1299,7 @@ impl Config {
.map(|change_id| change_id.inner.map(crate::find_recent_config_change_ids))
{
if !changes.is_empty() {
println!(
eprintln!(
"WARNING: There have been changes to x.py since you last updated:\n{}",
crate::human_readable_changes(&changes)
);
@ -1558,13 +1565,11 @@ impl Config {
}
if cargo_clippy.is_some() && rustc.is_none() {
println!(
eprintln!(
"WARNING: Using `build.cargo-clippy` without `build.rustc` usually fails due to toolchain conflict."
);
}
config.initial_cargo_clippy = cargo_clippy;
config.initial_rustc = if let Some(rustc) = rustc {
if !flags.skip_stage0_validation {
config.check_stage0_version(&rustc, "rustc");
@ -1580,6 +1585,10 @@ impl Config {
.join(exe("rustc", config.build))
};
config.initial_sysroot = config.initial_rustc.ancestors().nth(2).unwrap().into();
config.initial_cargo_clippy = cargo_clippy;
config.initial_cargo = if let Some(cargo) = cargo {
if !flags.skip_stage0_validation {
config.check_stage0_version(&cargo, "cargo");
@ -1587,12 +1596,7 @@ impl Config {
cargo
} else {
config.download_beta_toolchain();
config
.out
.join(config.build)
.join("stage0")
.join("bin")
.join(exe("cargo", config.build))
config.initial_sysroot.join("bin").join(exe("cargo", config.build))
};
// NOTE: it's important this comes *after* we set `initial_rustc` just above.
@ -1634,7 +1638,6 @@ impl Config {
set(&mut config.docs_minification, docs_minification);
set(&mut config.docs, docs);
set(&mut config.locked_deps, locked_deps);
set(&mut config.vendor, vendor);
set(&mut config.full_bootstrap, full_bootstrap);
set(&mut config.extended, extended);
config.tools = tools;
@ -1665,7 +1668,7 @@ impl Config {
}
config.llvm_assertions =
toml.llvm.as_ref().map_or(false, |llvm| llvm.assertions.unwrap_or(false));
toml.llvm.as_ref().is_some_and(|llvm| llvm.assertions.unwrap_or(false));
// Store off these values as options because if they're not provided
// we'll infer default values for them later
@ -1713,6 +1716,12 @@ impl Config {
config.in_tree_llvm_info = GitInfo::new(false, &config.src.join("src/llvm-project"));
config.in_tree_gcc_info = GitInfo::new(false, &config.src.join("src/gcc"));
config.vendor = vendor.unwrap_or(
config.rust_info.is_from_tarball()
&& config.src.join("vendor").exists()
&& config.src.join(".cargo/config.toml").exists(),
);
if let Some(rust) = toml.rust {
let Rust {
optimize: optimize_toml,
@ -1843,7 +1852,7 @@ impl Config {
// FIXME: Remove this option at the end of 2024.
if parallel_compiler.is_some() {
println!(
eprintln!(
"WARNING: The `rust.parallel-compiler` option is deprecated and does nothing. The parallel compiler (with one thread) is now the default"
);
}
@ -1875,7 +1884,7 @@ impl Config {
if available_backends.contains(&backend) {
panic!("Invalid value '{s}' for 'rust.codegen-backends'. Instead, please use '{backend}'.");
} else {
println!("HELP: '{s}' for 'rust.codegen-backends' might fail. \
eprintln!("HELP: '{s}' for 'rust.codegen-backends' might fail. \
Codegen backends are mostly defined without the '{CODEGEN_BACKEND_PREFIX}' prefix. \
In this case, it would be referred to as '{backend}'.");
}
@ -1904,7 +1913,7 @@ impl Config {
// tests may fail due to using a different channel than the one used by the compiler during tests.
if let Some(commit) = &config.download_rustc_commit {
if is_user_configured_rust_channel {
println!(
eprintln!(
"WARNING: `rust.download-rustc` is enabled. The `rust.channel` option will be overridden by the CI rustc's channel."
);
@ -1994,10 +2003,10 @@ impl Config {
if config.llvm_from_ci {
let warn = |option: &str| {
println!(
eprintln!(
"WARNING: `{option}` will only be used on `compiler/rustc_llvm` build, not for the LLVM build."
);
println!(
eprintln!(
"HELP: To use `{option}` for LLVM builds, set `download-ci-llvm` option to false."
);
};
@ -2016,12 +2025,12 @@ impl Config {
// if they've chosen a different value.
if libzstd.is_some() {
println!(
eprintln!(
"WARNING: when using `download-ci-llvm`, the local `llvm.libzstd` option, \
like almost all `llvm.*` options, will be ignored and set by the LLVM CI \
artifacts builder config."
);
println!(
eprintln!(
"HELP: To use `llvm.libzstd` for LLVM/LLD builds, set `download-ci-llvm` option to false."
);
}
@ -2090,7 +2099,7 @@ impl Config {
if available_backends.contains(&backend) {
panic!("Invalid value '{s}' for 'target.{triple}.codegen-backends'. Instead, please use '{backend}'.");
} else {
println!("HELP: '{s}' for 'target.{triple}.codegen-backends' might fail. \
eprintln!("HELP: '{s}' for 'target.{triple}.codegen-backends' might fail. \
Codegen backends are mostly defined without the '{CODEGEN_BACKEND_PREFIX}' prefix. \
In this case, it would be referred to as '{backend}'.");
}
@ -2306,7 +2315,7 @@ impl Config {
if self.dry_run() {
return Ok(());
}
self.verbose(|| println!("running: {cmd:?}"));
self.verbose(|| eprintln!("running: {cmd:?}"));
build_helper::util::try_run(cmd, self.is_verbose())
}
@ -2481,7 +2490,7 @@ impl Config {
// This happens when LLVM submodule is updated in CI, we should disable ci-rustc without an error
// to not break CI. For non-CI environments, we should return an error.
if CiEnv::is_ci() {
println!("WARNING: LLVM submodule has changes, `download-rustc` will be disabled.");
eprintln!("WARNING: LLVM submodule has changes, `download-rustc` will be disabled.");
return None;
} else {
panic!("ERROR: LLVM submodule has changes, `download-rustc` can't be used.");
@ -2492,8 +2501,8 @@ impl Config {
let ci_config_toml = match self.get_builder_toml("ci-rustc") {
Ok(ci_config_toml) => ci_config_toml,
Err(e) if e.to_string().contains("unknown field") => {
println!("WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled.");
println!("HELP: Consider rebasing to a newer commit if available.");
eprintln!("WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled.");
eprintln!("HELP: Consider rebasing to a newer commit if available.");
return None;
},
Err(e) => {
@ -2507,6 +2516,7 @@ impl Config {
// Check the config compatibility
// FIXME: this doesn't cover `--set` flags yet.
let res = check_incompatible_options_for_ci_rustc(
self.build,
current_config_toml,
ci_config_toml,
);
@ -2517,7 +2527,7 @@ impl Config {
.is_some_and(|s| s == "1" || s == "true");
if disable_ci_rustc_if_incompatible && res.is_err() {
println!("WARNING: download-rustc is disabled with `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` env.");
eprintln!("WARNING: download-rustc is disabled with `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` env.");
return None;
}
@ -2702,7 +2712,7 @@ impl Config {
return;
}
println!("Updating submodule {relative_path}");
eprintln!("Updating submodule {relative_path}");
self.check_run(
helpers::git(Some(&self.src))
.run_always()
@ -2825,7 +2835,7 @@ impl Config {
Some(StringOrBool::Bool(true)) => false,
Some(StringOrBool::String(s)) if s == "if-unchanged" => {
if !self.rust_info.is_managed_git_subrepository() {
println!(
eprintln!(
"ERROR: `download-rustc=if-unchanged` is only compatible with Git managed sources."
);
crate::exit!(1);
@ -2858,10 +2868,10 @@ impl Config {
if if_unchanged {
return None;
}
println!("ERROR: could not find commit hash for downloading rustc");
println!("HELP: maybe your repository history is too shallow?");
println!("HELP: consider setting `rust.download-rustc=false` in config.toml");
println!("HELP: or fetch enough history to include one upstream commit");
eprintln!("ERROR: could not find commit hash for downloading rustc");
eprintln!("HELP: maybe your repository history is too shallow?");
eprintln!("HELP: consider setting `rust.download-rustc=false` in config.toml");
eprintln!("HELP: or fetch enough history to include one upstream commit");
crate::exit!(1);
}
};
@ -2900,7 +2910,7 @@ impl Config {
let if_unchanged = || {
if self.rust_info.is_from_tarball() {
// Git is needed for running "if-unchanged" logic.
println!(
eprintln!(
"WARNING: 'if-unchanged' has no effect on tarball sources; ignoring `download-ci-llvm`."
);
return false;
@ -2949,10 +2959,10 @@ impl Config {
// Only commits merged by bors will have CI artifacts.
let commit = get_closest_merge_commit(Some(&self.src), &self.git_config(), &[]).unwrap();
if commit.is_empty() {
println!("error: could not find commit hash for downloading components from CI");
println!("help: maybe your repository history is too shallow?");
println!("help: consider disabling `{option_name}`");
println!("help: or fetch enough history to include one upstream commit");
eprintln!("error: could not find commit hash for downloading components from CI");
eprintln!("help: maybe your repository history is too shallow?");
eprintln!("help: consider disabling `{option_name}`");
eprintln!("help: or fetch enough history to include one upstream commit");
crate::exit!(1);
}
@ -2964,14 +2974,14 @@ impl Config {
if has_changes {
if if_unchanged {
if self.is_verbose() {
println!(
eprintln!(
"warning: saw changes to one of {modified_paths:?} since {commit}; \
ignoring `{option_name}`"
);
}
return None;
}
println!(
eprintln!(
"warning: `{option_name}` is enabled, but there are changes to one of {modified_paths:?}"
);
}
@ -3008,7 +3018,7 @@ pub(crate) fn check_incompatible_options_for_ci_llvm(
($current:expr, $expected:expr) => {
if let Some(current) = &$current {
if Some(current) != $expected.as_ref() {
println!(
eprintln!(
"WARNING: `llvm.{}` has no effect with `llvm.download-ci-llvm`. \
Current value: {:?}, Expected value(s): {}{:?}",
stringify!($expected).replace("_", "-"),
@ -3088,17 +3098,18 @@ pub(crate) fn check_incompatible_options_for_ci_llvm(
/// Compares the current Rust options against those in the CI rustc builder and detects any incompatible options.
/// It does this by destructuring the `Rust` instance to make sure every `Rust` field is covered and not missing.
fn check_incompatible_options_for_ci_rustc(
host: TargetSelection,
current_config_toml: TomlConfig,
ci_config_toml: TomlConfig,
) -> Result<(), String> {
macro_rules! err {
($current:expr, $expected:expr) => {
($current:expr, $expected:expr, $config_section:expr) => {
if let Some(current) = &$current {
if Some(current) != $expected.as_ref() {
return Err(format!(
"ERROR: Setting `rust.{}` is incompatible with `rust.download-rustc`. \
"ERROR: Setting `{}` is incompatible with `rust.download-rustc`. \
Current value: {:?}, Expected value(s): {}{:?}",
stringify!($expected).replace("_", "-"),
format!("{}.{}", $config_section, stringify!($expected).replace("_", "-")),
$current,
if $expected.is_some() { "None/" } else { "" },
$expected,
@ -3109,13 +3120,13 @@ fn check_incompatible_options_for_ci_rustc(
}
macro_rules! warn {
($current:expr, $expected:expr) => {
($current:expr, $expected:expr, $config_section:expr) => {
if let Some(current) = &$current {
if Some(current) != $expected.as_ref() {
println!(
"WARNING: `rust.{}` has no effect with `rust.download-rustc`. \
eprintln!(
"WARNING: `{}` has no effect with `rust.download-rustc`. \
Current value: {:?}, Expected value(s): {}{:?}",
stringify!($expected).replace("_", "-"),
format!("{}.{}", $config_section, stringify!($expected).replace("_", "-")),
$current,
if $expected.is_some() { "None/" } else { "" },
$expected,
@ -3125,6 +3136,31 @@ fn check_incompatible_options_for_ci_rustc(
};
}
let current_profiler = current_config_toml.build.as_ref().and_then(|b| b.profiler);
let profiler = ci_config_toml.build.as_ref().and_then(|b| b.profiler);
err!(current_profiler, profiler, "build");
let current_optimized_compiler_builtins =
current_config_toml.build.as_ref().and_then(|b| b.optimized_compiler_builtins);
let optimized_compiler_builtins =
ci_config_toml.build.as_ref().and_then(|b| b.optimized_compiler_builtins);
err!(current_optimized_compiler_builtins, optimized_compiler_builtins, "build");
// We always build the in-tree compiler on cross targets, so we only care
// about the host target here.
let host_str = host.to_string();
if let Some(current_cfg) = current_config_toml.target.as_ref().and_then(|c| c.get(&host_str)) {
if current_cfg.profiler.is_some() {
let ci_target_toml = ci_config_toml.target.as_ref().and_then(|c| c.get(&host_str));
let ci_cfg = ci_target_toml.ok_or(format!(
"Target specific config for '{host_str}' is not present for CI-rustc"
))?;
let profiler = &ci_cfg.profiler;
err!(current_cfg.profiler, profiler, "build");
}
}
let (Some(current_rust_config), Some(ci_rust_config)) =
(current_config_toml.rust, ci_config_toml.rust)
else {
@ -3198,24 +3234,24 @@ fn check_incompatible_options_for_ci_rustc(
// If the option belongs to the first category, we call `err` macro for a hard error;
// otherwise, we just print a warning with `warn` macro.
err!(current_rust_config.optimize, optimize);
err!(current_rust_config.randomize_layout, randomize_layout);
err!(current_rust_config.debug_logging, debug_logging);
err!(current_rust_config.debuginfo_level_rustc, debuginfo_level_rustc);
err!(current_rust_config.rpath, rpath);
err!(current_rust_config.strip, strip);
err!(current_rust_config.lld_mode, lld_mode);
err!(current_rust_config.llvm_tools, llvm_tools);
err!(current_rust_config.llvm_bitcode_linker, llvm_bitcode_linker);
err!(current_rust_config.jemalloc, jemalloc);
err!(current_rust_config.default_linker, default_linker);
err!(current_rust_config.stack_protector, stack_protector);
err!(current_rust_config.lto, lto);
err!(current_rust_config.std_features, std_features);
err!(current_rust_config.optimize, optimize, "rust");
err!(current_rust_config.randomize_layout, randomize_layout, "rust");
err!(current_rust_config.debug_logging, debug_logging, "rust");
err!(current_rust_config.debuginfo_level_rustc, debuginfo_level_rustc, "rust");
err!(current_rust_config.rpath, rpath, "rust");
err!(current_rust_config.strip, strip, "rust");
err!(current_rust_config.lld_mode, lld_mode, "rust");
err!(current_rust_config.llvm_tools, llvm_tools, "rust");
err!(current_rust_config.llvm_bitcode_linker, llvm_bitcode_linker, "rust");
err!(current_rust_config.jemalloc, jemalloc, "rust");
err!(current_rust_config.default_linker, default_linker, "rust");
err!(current_rust_config.stack_protector, stack_protector, "rust");
err!(current_rust_config.lto, lto, "rust");
err!(current_rust_config.std_features, std_features, "rust");
warn!(current_rust_config.channel, channel);
warn!(current_rust_config.description, description);
warn!(current_rust_config.incremental, incremental);
warn!(current_rust_config.channel, channel, "rust");
warn!(current_rust_config.description, description, "rust");
warn!(current_rust_config.incremental, incremental, "rust");
Ok(())
}

View file

@ -196,12 +196,12 @@ impl Flags {
if let Ok(HelpVerboseOnly { help: true, verbose: 1.., cmd: subcommand }) =
HelpVerboseOnly::try_parse_from(normalize_args(args))
{
println!("NOTE: updating submodules before printing available paths");
eprintln!("NOTE: updating submodules before printing available paths");
let config = Config::parse(Self::parse(&[String::from("build")]));
let build = Build::new(config);
let paths = Builder::get_help(&build, subcommand);
if let Some(s) = paths {
println!("{s}");
eprintln!("{s}");
} else {
panic!("No paths available for subcommand `{}`", subcommand.as_str());
}

View file

@ -77,7 +77,7 @@ impl Config {
if self.dry_run() && !cmd.run_always {
return true;
}
self.verbose(|| println!("running: {cmd:?}"));
self.verbose(|| eprintln!("running: {cmd:?}"));
check_run(cmd, self.is_verbose())
}
@ -144,7 +144,7 @@ impl Config {
/// Please see <https://nixos.org/patchelf.html> for more information
fn fix_bin_or_dylib(&self, fname: &Path) {
assert_eq!(SHOULD_FIX_BINS_AND_DYLIBS.get(), Some(&true));
println!("attempting to patch {}", fname.display());
eprintln!("attempting to patch {}", fname.display());
// Only build `.nix-deps` once.
static NIX_DEPS_DIR: OnceLock<PathBuf> = OnceLock::new();
@ -206,7 +206,7 @@ impl Config {
}
fn download_file(&self, url: &str, dest_path: &Path, help_on_error: &str) {
self.verbose(|| println!("download {url}"));
self.verbose(|| eprintln!("download {url}"));
// Use a temporary file in case we crash while downloading, to avoid a corrupt download in cache/.
let tempfile = self.tempdir().join(dest_path.file_name().unwrap());
// While bootstrap itself only supports http and https downloads, downstream forks might
@ -226,7 +226,7 @@ impl Config {
}
fn download_http_with_retries(&self, tempfile: &Path, url: &str, help_on_error: &str) {
println!("downloading {url}");
eprintln!("downloading {url}");
// Try curl. If that fails and we are on windows, fallback to PowerShell.
// options should be kept in sync with
// src/bootstrap/src/core/download.rs
@ -341,7 +341,7 @@ impl Config {
short_path = short_path.strip_prefix(pattern).unwrap_or(short_path);
let dst_path = dst.join(short_path);
self.verbose(|| {
println!("extracting {} to {}", original_path.display(), dst.display())
eprintln!("extracting {} to {}", original_path.display(), dst.display())
});
if !t!(member.unpack_in(dst)) {
panic!("path traversal attack ??");
@ -365,7 +365,7 @@ impl Config {
pub(crate) fn verify(&self, path: &Path, expected: &str) -> bool {
use sha2::Digest;
self.verbose(|| println!("verifying {}", path.display()));
self.verbose(|| eprintln!("verifying {}", path.display()));
if self.dry_run() {
return false;
@ -391,7 +391,7 @@ impl Config {
let verified = checksum == expected;
if !verified {
println!(
eprintln!(
"invalid checksum: \n\
found: {checksum}\n\
expected: {expected}",
@ -421,15 +421,14 @@ enum DownloadSource {
/// Functions that are only ever called once, but named for clarify and to avoid thousand-line functions.
impl Config {
pub(crate) fn download_clippy(&self) -> PathBuf {
self.verbose(|| println!("downloading stage0 clippy artifacts"));
self.verbose(|| eprintln!("downloading stage0 clippy artifacts"));
let date = &self.stage0_metadata.compiler.date;
let version = &self.stage0_metadata.compiler.version;
let host = self.build;
let bin_root = self.out.join(host).join("stage0");
let clippy_stamp = bin_root.join(".clippy-stamp");
let cargo_clippy = bin_root.join("bin").join(exe("cargo-clippy", host));
let clippy_stamp = self.initial_sysroot.join(".clippy-stamp");
let cargo_clippy = self.initial_sysroot.join("bin").join(exe("cargo-clippy", host));
if cargo_clippy.exists() && !program_out_of_date(&clippy_stamp, date) {
return cargo_clippy;
}
@ -519,7 +518,7 @@ impl Config {
}
pub(crate) fn download_ci_rustc(&self, commit: &str) {
self.verbose(|| println!("using downloaded stage2 artifacts from CI (commit {commit})"));
self.verbose(|| eprintln!("using downloaded stage2 artifacts from CI (commit {commit})"));
let version = self.artifact_version_part(commit);
// download-rustc doesn't need its own cargo, it can just use beta's. But it does need the
@ -540,7 +539,7 @@ impl Config {
#[cfg(not(feature = "bootstrap-self-test"))]
pub(crate) fn download_beta_toolchain(&self) {
self.verbose(|| println!("downloading stage0 beta artifacts"));
self.verbose(|| eprintln!("downloading stage0 beta artifacts"));
let date = &self.stage0_metadata.compiler.date;
let version = &self.stage0_metadata.compiler.version;
@ -678,7 +677,7 @@ impl Config {
return;
} else {
self.verbose(|| {
println!(
eprintln!(
"ignoring cached file {} due to failed verification",
tarball.display()
)
@ -777,10 +776,10 @@ download-rustc = false
t!(check_incompatible_options_for_ci_llvm(current_config_toml, ci_config_toml));
}
Err(e) if e.to_string().contains("unknown field") => {
println!(
eprintln!(
"WARNING: CI LLVM has some fields that are no longer supported in bootstrap; download-ci-llvm will be disabled."
);
println!("HELP: Consider rebasing to a newer commit if available.");
eprintln!("HELP: Consider rebasing to a newer commit if available.");
}
Err(e) => {
eprintln!("ERROR: Failed to parse CI LLVM config.toml: {e}");
@ -830,7 +829,7 @@ download-rustc = false
fn path_is_dylib(path: &Path) -> bool {
// The .so is not necessarily the extension, it might be libLLVM.so.18.1
path.to_str().map_or(false, |path| path.contains(".so"))
path.to_str().is_some_and(|path| path.contains(".so"))
}
/// Checks whether the CI rustc is available for the given target triple.

View file

@ -135,19 +135,15 @@ pub fn check(build: &mut Build) {
// We need cmake, but only if we're actually building LLVM or sanitizers.
let building_llvm = !build.config.llvm_from_ci
&& build
.hosts
.iter()
.map(|host| {
build.config.llvm_enabled(*host)
&& build
.config
.target_config
.get(host)
.map(|config| config.llvm_config.is_none())
.unwrap_or(true)
})
.any(|build_llvm_ourselves| build_llvm_ourselves);
&& build.hosts.iter().any(|host| {
build.config.llvm_enabled(*host)
&& build
.config
.target_config
.get(host)
.map(|config| config.llvm_config.is_none())
.unwrap_or(true)
});
let need_cmake = building_llvm || build.config.any_sanitizers_to_build();
if need_cmake && cmd_finder.maybe_have("cmake").is_none() {
@ -241,11 +237,11 @@ than building it.
stage0_supported_target_list.intersection(&missing_targets_hashset).collect();
if !duplicated_targets.is_empty() {
println!(
eprintln!(
"Following targets supported from the stage0 compiler, please remove them from STAGE0_MISSING_TARGETS list."
);
for duplicated_target in duplicated_targets {
println!(" {duplicated_target}");
eprintln!(" {duplicated_target}");
}
std::process::exit(1);
}

View file

@ -158,7 +158,7 @@ pub struct Build {
initial_rustc: PathBuf,
initial_cargo: PathBuf,
initial_lld: PathBuf,
initial_libdir: PathBuf,
initial_relative_libdir: PathBuf,
initial_sysroot: PathBuf,
// Runtime state filled in later on
@ -312,46 +312,19 @@ impl Build {
let in_tree_llvm_info = config.in_tree_llvm_info.clone();
let in_tree_gcc_info = config.in_tree_gcc_info.clone();
let initial_target_libdir_str = if config.dry_run() {
"/dummy/lib/path/to/lib/".to_string()
} else {
output(
Command::new(&config.initial_rustc)
.arg("--target")
.arg(config.build.rustc_target_arg())
.arg("--print")
.arg("target-libdir"),
)
};
let initial_target_libdir_str =
config.initial_sysroot.join("lib/rustlib").join(config.build).join("lib");
let initial_target_dir = Path::new(&initial_target_libdir_str).parent().unwrap();
let initial_lld = initial_target_dir.join("bin").join("rust-lld");
let initial_sysroot = if config.dry_run() {
"/dummy".to_string()
} else {
output(Command::new(&config.initial_rustc).arg("--print").arg("sysroot"))
}
.trim()
.to_string();
// FIXME(Zalathar): Determining this path occasionally fails locally for
// unknown reasons, so we print some extra context to help track down why.
let find_initial_libdir = || {
let initial_libdir =
initial_target_dir.parent()?.parent()?.strip_prefix(&initial_sysroot).ok()?;
Some(initial_libdir.to_path_buf())
};
let Some(initial_libdir) = find_initial_libdir() else {
panic!(
"couldn't determine `initial_libdir`:
- config.initial_rustc: {rustc:?}
- initial_target_libdir_str: {initial_target_libdir_str:?}
- initial_target_dir: {initial_target_dir:?}
- initial_sysroot: {initial_sysroot:?}
",
rustc = config.initial_rustc,
);
};
let initial_relative_libdir = initial_target_dir
.ancestors()
.nth(2)
.unwrap()
.strip_prefix(&config.initial_sysroot)
.expect("Couldnt determine initial relative libdir.")
.to_path_buf();
let version = std::fs::read_to_string(src.join("src").join("version"))
.expect("failed to read src/version");
@ -380,11 +353,11 @@ impl Build {
}
let mut build = Build {
initial_lld,
initial_relative_libdir,
initial_rustc: config.initial_rustc.clone(),
initial_cargo: config.initial_cargo.clone(),
initial_lld,
initial_libdir,
initial_sysroot: initial_sysroot.into(),
initial_sysroot: config.initial_sysroot.clone(),
local_rebuild: config.local_rebuild,
fail_fast: config.cmd.fail_fast(),
doc_tests: config.cmd.doc_tests(),
@ -433,11 +406,11 @@ impl Build {
.unwrap()
.trim();
if local_release.split('.').take(2).eq(version.split('.').take(2)) {
build.verbose(|| println!("auto-detected local-rebuild {local_release}"));
build.verbose(|| eprintln!("auto-detected local-rebuild {local_release}"));
build.local_rebuild = true;
}
build.verbose(|| println!("finding compilers"));
build.verbose(|| eprintln!("finding compilers"));
utils::cc_detect::find(&build);
// When running `setup`, the profile is about to change, so any requirements we have now may
// be different on the next invocation. Don't check for them until the next time x.py is
@ -445,7 +418,7 @@ impl Build {
//
// Similarly, for `setup` we don't actually need submodules or cargo metadata.
if !matches!(build.config.cmd, Subcommand::Setup { .. }) {
build.verbose(|| println!("running sanity check"));
build.verbose(|| eprintln!("running sanity check"));
crate::core::sanity::check(&mut build);
// Make sure we update these before gathering metadata so we don't get an error about missing
@ -463,7 +436,7 @@ impl Build {
// Now, update all existing submodules.
build.update_existing_submodules();
build.verbose(|| println!("learning about cargo"));
build.verbose(|| eprintln!("learning about cargo"));
crate::core::metadata::build(&mut build);
}
@ -632,7 +605,7 @@ impl Build {
let stamp = dir.join(".stamp");
let mut cleared = false;
if mtime(&stamp) < mtime(input) {
self.verbose(|| println!("Dirty - {}", dir.display()));
self.verbose(|| eprintln!("Dirty - {}", dir.display()));
let _ = fs::remove_dir_all(dir);
cleared = true;
} else if stamp.exists() {
@ -917,7 +890,7 @@ impl Build {
let executed_at = std::panic::Location::caller();
self.verbose(|| {
println!("running: {command:?} (created at {created_at}, executed at {executed_at})")
eprintln!("running: {command:?} (created at {created_at}, executed at {executed_at})")
});
let cmd = command.as_command_mut();
@ -974,7 +947,7 @@ Executed at: {executed_at}"#,
let fail = |message: &str, output: CommandOutput| -> ! {
if self.is_verbose() {
println!("{message}");
eprintln!("{message}");
} else {
let (stdout, stderr) = (output.stdout_if_present(), output.stderr_if_present());
// If the command captures output, the user would not see any indication that
@ -984,16 +957,16 @@ Executed at: {executed_at}"#,
if let Some(stdout) =
output.stdout_if_present().take_if(|s| !s.trim().is_empty())
{
println!("STDOUT:\n{stdout}\n");
eprintln!("STDOUT:\n{stdout}\n");
}
if let Some(stderr) =
output.stderr_if_present().take_if(|s| !s.trim().is_empty())
{
println!("STDERR:\n{stderr}\n");
eprintln!("STDERR:\n{stderr}\n");
}
println!("Command {command:?} has failed. Rerun with -v to see more details.");
eprintln!("Command {command:?} has failed. Rerun with -v to see more details.");
} else {
println!("Command has failed. Rerun with -v to see more details.");
eprintln!("Command has failed. Rerun with -v to see more details.");
}
}
exit!(1);
@ -1038,7 +1011,7 @@ Executed at: {executed_at}"#,
match self.config.dry_run {
DryRun::SelfCheck => (),
DryRun::Disabled | DryRun::UserSelected => {
println!("{msg}");
eprintln!("{msg}");
}
}
}
@ -1693,7 +1666,7 @@ Executed at: {executed_at}"#,
if self.config.dry_run() {
return;
}
self.verbose_than(1, || println!("Copy/Link {src:?} to {dst:?}"));
self.verbose_than(1, || eprintln!("Copy/Link {src:?} to {dst:?}"));
if src == dst {
return;
}
@ -1802,7 +1775,7 @@ Executed at: {executed_at}"#,
return;
}
let dst = dstdir.join(src.file_name().unwrap());
self.verbose_than(1, || println!("Install {src:?} to {dst:?}"));
self.verbose_than(1, || eprintln!("Install {src:?} to {dst:?}"));
t!(fs::create_dir_all(dstdir));
if !src.exists() {
panic!("ERROR: File \"{}\" not found!", src.display());

View file

@ -155,15 +155,15 @@ pub fn find_target(build: &Build, target: TargetSelection) {
build.cxx.borrow_mut().insert(target, compiler);
}
build.verbose(|| println!("CC_{} = {:?}", target.triple, build.cc(target)));
build.verbose(|| println!("CFLAGS_{} = {cflags:?}", target.triple));
build.verbose(|| eprintln!("CC_{} = {:?}", target.triple, build.cc(target)));
build.verbose(|| eprintln!("CFLAGS_{} = {cflags:?}", target.triple));
if let Ok(cxx) = build.cxx(target) {
let cxxflags = build.cflags(target, GitRepo::Rustc, CLang::Cxx);
build.verbose(|| println!("CXX_{} = {cxx:?}", target.triple));
build.verbose(|| println!("CXXFLAGS_{} = {cxxflags:?}", target.triple));
build.verbose(|| eprintln!("CXX_{} = {cxx:?}", target.triple));
build.verbose(|| eprintln!("CXXFLAGS_{} = {cxxflags:?}", target.triple));
}
if let Some(ar) = ar {
build.verbose(|| println!("AR_{} = {ar:?}", target.triple));
build.verbose(|| eprintln!("AR_{} = {ar:?}", target.triple));
build.ar.borrow_mut().insert(target, ar);
}

View file

@ -310,4 +310,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
severity: ChangeSeverity::Warning,
summary: "Revert `rust.download-rustc` global default to `false` and only use `rust.download-rustc = \"if-unchanged\"` default for library and tools profile. As alt CI rustc is built without debug assertions, `rust.debug-assertions = true` will now inhibit downloading CI rustc.",
},
ChangeInfo {
change_id: 133853,
severity: ChangeSeverity::Info,
summary: "`build.vendor` is now enabled by default for dist/tarball sources when 'vendor' directory and '.cargo/config.toml' file are present.",
},
];

View file

@ -55,7 +55,7 @@ pub fn exe(name: &str, target: TargetSelection) -> String {
/// Returns `true` if the file name given looks like a dynamic library.
pub fn is_dylib(path: &Path) -> bool {
path.extension().and_then(|ext| ext.to_str()).map_or(false, |ext| {
path.extension().and_then(|ext| ext.to_str()).is_some_and(|ext| {
ext == "dylib" || ext == "so" || ext == "dll" || (ext == "a" && is_aix_shared_archive(path))
})
}
@ -135,7 +135,7 @@ impl Drop for TimeIt {
fn drop(&mut self) {
let time = self.1.elapsed();
if !self.0 {
println!("\tfinished in {}.{:03} seconds", time.as_secs(), time.subsec_millis());
eprintln!("\tfinished in {}.{:03} seconds", time.as_secs(), time.subsec_millis());
}
}
}
@ -267,12 +267,12 @@ pub fn check_run(cmd: &mut BootstrapCommand, print_cmd_on_fail: bool) -> bool {
let status = match cmd.as_command_mut().status() {
Ok(status) => status,
Err(e) => {
println!("failed to execute command: {cmd:?}\nERROR: {e}");
eprintln!("failed to execute command: {cmd:?}\nERROR: {e}");
return false;
}
};
if !status.success() && print_cmd_on_fail {
println!(
eprintln!(
"\n\ncommand did not execute successfully: {cmd:?}\n\
expected success, got: {status}\n\n"
);

View file

@ -15,11 +15,12 @@ pub unsafe fn setup(build: &mut crate::Build) {
///
/// Most of the time when you're running a build system (e.g., make) you expect
/// Ctrl-C or abnormal termination to actually terminate the entire tree of
/// process in play, not just the one at the top. This currently works "by
/// processes in play. This currently works "by
/// default" on Unix platforms because Ctrl-C actually sends a signal to the
/// *process group* rather than the parent process, so everything will get torn
/// down. On Windows, however, this does not happen and Ctrl-C just kills the
/// parent process.
/// *process group* so everything will get torn
/// down. On Windows, however, Ctrl-C is only sent to processes in the same console.
/// If a process is detached or attached to another console, it won't receive the
/// signal.
///
/// To achieve the same semantics on Windows we use Job Objects to ensure that
/// all processes die at the same time. Job objects have a mode of operation
@ -87,15 +88,7 @@ mod for_windows {
);
assert!(r.is_ok(), "{}", io::Error::last_os_error());
// Assign our process to this job object. Note that if this fails, one very
// likely reason is that we are ourselves already in a job object! This can
// happen on the build bots that we've got for Windows, or if just anyone
// else is instrumenting the build. In this case we just bail out
// immediately and assume that they take care of it.
//
// Also note that nested jobs (why this might fail) are supported in recent
// versions of Windows, but the version of Windows that our bots are running
// at least don't support nested job objects.
// Assign our process to this job object.
let r = AssignProcessToJobObject(job, GetCurrentProcess());
if r.is_err() {
CloseHandle(job).ok();
@ -124,14 +117,19 @@ mod for_windows {
// (only when wrongly setting the environmental variable),
// it might be better to improve the experience of the second case
// when users have interrupted the parent process and we haven't finish
// duplicating the handle yet. We just need close the job object if that occurs.
CloseHandle(job).ok();
// duplicating the handle yet.
return;
}
};
let mut parent_handle = HANDLE::default();
let r = DuplicateHandle(
// If this fails, well at least we tried! An example of DuplicateHandle
// failing in the past has been when the wrong python2 package spawned this
// build system (e.g., the `python2` package in MSYS instead of
// `mingw-w64-x86_64-python2`). Not sure why it failed, but the "failure
// mode" here is that we only clean everything up when the build system
// dies, not when the python parent does, so not too bad.
let _ = DuplicateHandle(
GetCurrentProcess(),
job,
parent,
@ -140,15 +138,6 @@ mod for_windows {
false,
DUPLICATE_SAME_ACCESS,
);
// If this failed, well at least we tried! An example of DuplicateHandle
// failing in the past has been when the wrong python2 package spawned this
// build system (e.g., the `python2` package in MSYS instead of
// `mingw-w64-x86_64-python2`). Not sure why it failed, but the "failure
// mode" here is that we only clean everything up when the build system
// dies, not when the python parent does, so not too bad.
if r.is_err() {
CloseHandle(job).ok();
}
CloseHandle(parent).ok();
}
}

View file

@ -56,7 +56,7 @@ impl BuildMetrics {
running_steps: Vec::new(),
system_info: System::new_with_specifics(
RefreshKind::new().with_cpu(CpuRefreshKind::everything()),
RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
),
timer_start: None,
invocation_timer_start: Instant::now(),
@ -161,8 +161,9 @@ impl BuildMetrics {
let dest = build.out.join("metrics.json");
let mut system =
System::new_with_specifics(RefreshKind::new().with_cpu(CpuRefreshKind::everything()));
let mut system = System::new_with_specifics(
RefreshKind::nothing().with_cpu(CpuRefreshKind::everything()),
);
system.refresh_cpu_usage();
system.refresh_memory();
@ -184,7 +185,7 @@ impl BuildMetrics {
if version.format_version == CURRENT_FORMAT_VERSION {
t!(serde_json::from_slice::<JsonRoot>(&contents)).invocations
} else {
println!(
eprintln!(
"WARNING: overriding existing build/metrics.json, as it's not \
compatible with build metrics format version {CURRENT_FORMAT_VERSION}."
);

View file

@ -56,7 +56,7 @@ fn run_tests(builder: &Builder<'_>, cmd: &mut BootstrapCommand, stream: bool) ->
let cmd = cmd.as_command_mut();
cmd.stdout(Stdio::piped());
builder.verbose(|| println!("running: {cmd:?}"));
builder.verbose(|| eprintln!("running: {cmd:?}"));
let mut process = cmd.spawn().unwrap();
@ -71,7 +71,7 @@ fn run_tests(builder: &Builder<'_>, cmd: &mut BootstrapCommand, stream: bool) ->
let result = process.wait_with_output().unwrap();
if !result.status.success() && builder.is_verbose() {
println!(
eprintln!(
"\n\ncommand did not execute successfully: {cmd:?}\n\
expected success, got: {}",
result.status
@ -135,7 +135,9 @@ impl<'a> Renderer<'a> {
if self.up_to_date_tests > 0 {
let n = self.up_to_date_tests;
let s = if n > 1 { "s" } else { "" };
println!("help: ignored {n} up-to-date test{s}; use `--force-rerun` to prevent this\n");
eprintln!(
"help: ignored {n} up-to-date test{s}; use `--force-rerun` to prevent this\n"
);
}
}
@ -185,12 +187,12 @@ impl<'a> Renderer<'a> {
}
fn render_test_outcome_verbose(&self, outcome: Outcome<'_>, test: &TestOutcome) {
print!("test {} ... ", test.name);
self.builder.colored_stdout(|stdout| outcome.write_long(stdout)).unwrap();
eprint!("test {} ... ", test.name);
self.builder.colored_stderr(|stdout| outcome.write_long(stdout)).unwrap();
if let Some(exec_time) = test.exec_time {
print!(" ({exec_time:.2?})");
eprint!(" ({exec_time:.2?})");
}
println!();
eprintln!();
}
fn render_test_outcome_terse(&mut self, outcome: Outcome<'_>, test: &TestOutcome) {
@ -198,45 +200,45 @@ impl<'a> Renderer<'a> {
if let Some(total) = self.tests_count {
let total = total.to_string();
let executed = format!("{:>width$}", self.executed_tests - 1, width = total.len());
print!(" {executed}/{total}");
eprint!(" {executed}/{total}");
}
println!();
eprintln!();
self.terse_tests_in_line = 0;
}
self.terse_tests_in_line += 1;
self.builder.colored_stdout(|stdout| outcome.write_short(stdout, &test.name)).unwrap();
self.builder.colored_stderr(|stdout| outcome.write_short(stdout, &test.name)).unwrap();
let _ = std::io::stdout().flush();
}
fn render_suite_outcome(&self, outcome: Outcome<'_>, suite: &SuiteOutcome) {
// The terse output doesn't end with a newline, so we need to add it ourselves.
if !self.builder.config.verbose_tests {
println!();
eprintln!();
}
if !self.failures.is_empty() {
println!("\nfailures:\n");
eprintln!("\nfailures:\n");
for failure in &self.failures {
if failure.stdout.is_some() || failure.message.is_some() {
println!("---- {} stdout ----", failure.name);
eprintln!("---- {} stdout ----", failure.name);
if let Some(stdout) = &failure.stdout {
println!("{stdout}");
eprintln!("{stdout}");
}
if let Some(message) = &failure.message {
println!("NOTE: {message}");
eprintln!("NOTE: {message}");
}
}
}
println!("\nfailures:");
eprintln!("\nfailures:");
for failure in &self.failures {
println!(" {}", failure.name);
eprintln!(" {}", failure.name);
}
}
if !self.benches.is_empty() {
println!("\nbenchmarks:");
eprintln!("\nbenchmarks:");
let mut rows = Vec::new();
for bench in &self.benches {
@ -251,13 +253,13 @@ impl<'a> Renderer<'a> {
let max_1 = rows.iter().map(|r| r.1.len()).max().unwrap_or(0);
let max_2 = rows.iter().map(|r| r.2.len()).max().unwrap_or(0);
for row in &rows {
println!(" {:<max_0$} {:>max_1$} {:>max_2$}", row.0, row.1, row.2);
eprintln!(" {:<max_0$} {:>max_1$} {:>max_2$}", row.0, row.1, row.2);
}
}
print!("\ntest result: ");
self.builder.colored_stdout(|stdout| outcome.write_long(stdout)).unwrap();
println!(
eprint!("\ntest result: ");
self.builder.colored_stderr(|stdout| outcome.write_long(stdout)).unwrap();
eprintln!(
". {} passed; {} failed; {} ignored; {} measured; {} filtered out{time}\n",
suite.passed,
suite.failed,
@ -274,7 +276,7 @@ impl<'a> Renderer<'a> {
fn render_message(&mut self, message: Message) {
match message {
Message::Suite(SuiteMessage::Started { test_count }) => {
println!("\nrunning {test_count} tests");
eprintln!("\nrunning {test_count} tests");
self.executed_tests = 0;
self.terse_tests_in_line = 0;
self.tests_count = Some(test_count);
@ -314,7 +316,7 @@ impl<'a> Renderer<'a> {
self.failures.push(outcome);
}
Message::Test(TestMessage::Timeout { name }) => {
println!("test {name} has been running for a long time");
eprintln!("test {name} has been running for a long time");
}
Message::Test(TestMessage::Started) => {} // Not useful
}

View file

@ -344,7 +344,7 @@ impl<'a> Tarball<'a> {
// For `x install` tarball files aren't needed, so we can speed up the process by not producing them.
let compression_profile = if self.builder.kind == Kind::Install {
self.builder.verbose(|| {
println!("Forcing dist.compression-profile = 'no-op' for `x install`.")
eprintln!("Forcing dist.compression-profile = 'no-op' for `x install`.")
});
// "no-op" indicates that the rust-installer won't produce compressed tarball sources.
"no-op"

View file

@ -40,12 +40,13 @@ import time
# Python 3.3 changed the value of `sys.platform` on Linux from "linux2" to just
# "linux". We check here with `.startswith` to keep compatibility with older
# Python versions (especially Python 2.7).
if sys.platform.startswith('linux'):
if sys.platform.startswith("linux"):
class State:
def __init__(self):
with open('/proc/stat', 'r') as file:
with open("/proc/stat", "r") as file:
data = file.readline().split()
if data[0] != 'cpu':
if data[0] != "cpu":
raise Exception('did not start with "cpu"')
self.user = int(data[1])
self.nice = int(data[2])
@ -69,10 +70,21 @@ if sys.platform.startswith('linux'):
steal = self.steal - prev.steal
guest = self.guest - prev.guest
guest_nice = self.guest_nice - prev.guest_nice
total = user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice
total = (
user
+ nice
+ system
+ idle
+ iowait
+ irq
+ softirq
+ steal
+ guest
+ guest_nice
)
return float(idle) / float(total) * 100
elif sys.platform == 'win32':
elif sys.platform == "win32":
from ctypes.wintypes import DWORD
from ctypes import Structure, windll, WinError, GetLastError, byref
@ -104,9 +116,10 @@ elif sys.platform == 'win32':
kernel = self.kernel - prev.kernel
return float(idle) / float(user + kernel) * 100
elif sys.platform == 'darwin':
elif sys.platform == "darwin":
from ctypes import *
libc = cdll.LoadLibrary('/usr/lib/libc.dylib')
libc = cdll.LoadLibrary("/usr/lib/libc.dylib")
class host_cpu_load_info_data_t(Structure):
_fields_ = [("cpu_ticks", c_uint * 4)]
@ -116,7 +129,7 @@ elif sys.platform == 'darwin':
c_uint,
c_int,
POINTER(host_cpu_load_info_data_t),
POINTER(c_int)
POINTER(c_int),
]
host_statistics.restype = c_int
@ -124,13 +137,14 @@ elif sys.platform == 'darwin':
CPU_STATE_SYSTEM = 1
CPU_STATE_IDLE = 2
CPU_STATE_NICE = 3
class State:
def __init__(self):
stats = host_cpu_load_info_data_t()
count = c_int(4) # HOST_CPU_LOAD_INFO_COUNT
count = c_int(4) # HOST_CPU_LOAD_INFO_COUNT
err = libc.host_statistics(
libc.mach_host_self(),
c_int(3), # HOST_CPU_LOAD_INFO
c_int(3), # HOST_CPU_LOAD_INFO
byref(stats),
byref(count),
)
@ -148,7 +162,7 @@ elif sys.platform == 'darwin':
return float(idle) / float(user + system + idle + nice) * 100.0
else:
print('unknown platform', sys.platform)
print("unknown platform", sys.platform)
sys.exit(1)
cur_state = State()

View file

@ -19,7 +19,7 @@ RUN sh /scripts/rustbuild-setup.sh
WORKDIR /tmp
COPY scripts/crosstool-ng-build.sh /scripts/
COPY host-x86_64/dist-arm-linux/arm-linux-gnueabi.defconfig /tmp/crosstool.defconfig
COPY host-aarch64/dist-arm-linux/arm-linux-gnueabi.defconfig /tmp/crosstool.defconfig
RUN /scripts/crosstool-ng-build.sh
COPY scripts/sccache.sh /scripts/

View file

@ -1,4 +1,4 @@
FROM ubuntu:23.04
FROM ubuntu:24.04
ARG DEBIAN_FRONTEND=noninteractive
COPY scripts/android-base-apt-get.sh /scripts/
@ -11,7 +11,8 @@ RUN . /scripts/android-ndk.sh && \
RUN dpkg --add-architecture i386 && \
apt-get update && \
apt-get install -y --no-install-recommends \
libgl1-mesa-glx \
libgl1 \
libglx-mesa0 \
libpulse0 \
libstdc++6:i386 \
openjdk-8-jre-headless \

View file

@ -1,4 +1,4 @@
FROM ubuntu:23.04
FROM ubuntu:24.04
COPY scripts/android-base-apt-get.sh /scripts/
RUN sh /scripts/android-base-apt-get.sh

View file

@ -1,4 +1,4 @@
FROM ubuntu:23.04
FROM ubuntu:24.04
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \

View file

@ -27,5 +27,5 @@ RUN echo "[rust]" > /config/nopt-std-config.toml
RUN echo "optimize = false" >> /config/nopt-std-config.toml
ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests
ENV SCRIPT python3 ../x.py test --stage 0 --config /config/nopt-std-config.toml library/std \
&& python3 ../x.py --stage 2 test
ARG SCRIPT_ARG
ENV SCRIPT=${SCRIPT_ARG}

View file

@ -24,10 +24,5 @@ COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu
# Skip some tests that are unlikely to be platform specific, to speed up
# this slow job.
ENV SCRIPT python3 ../x.py --stage 2 test \
--skip src/bootstrap \
--skip tests/rustdoc-js \
--skip src/tools/error_index_generator \
--skip src/tools/linkchecker
ARG SCRIPT_ARG
ENV SCRIPT=${SCRIPT_ARG}

View file

@ -8,78 +8,79 @@ import tempfile
from pathlib import Path
TARGET_AARCH64 = 'aarch64-unknown-uefi'
TARGET_I686 = 'i686-unknown-uefi'
TARGET_X86_64 = 'x86_64-unknown-uefi'
TARGET_AARCH64 = "aarch64-unknown-uefi"
TARGET_I686 = "i686-unknown-uefi"
TARGET_X86_64 = "x86_64-unknown-uefi"
def run(*cmd, capture=False, check=True, env=None, timeout=None):
"""Print and run a command, optionally capturing the output."""
cmd = [str(p) for p in cmd]
print(' '.join(cmd))
return subprocess.run(cmd,
capture_output=capture,
check=check,
env=env,
text=True,
timeout=timeout)
print(" ".join(cmd))
return subprocess.run(
cmd, capture_output=capture, check=check, env=env, text=True, timeout=timeout
)
def build_and_run(tmp_dir, target):
if target == TARGET_AARCH64:
boot_file_name = 'bootaa64.efi'
ovmf_dir = Path('/usr/share/AAVMF')
ovmf_code = 'AAVMF_CODE.fd'
ovmf_vars = 'AAVMF_VARS.fd'
qemu = 'qemu-system-aarch64'
machine = 'virt'
cpu = 'cortex-a72'
boot_file_name = "bootaa64.efi"
ovmf_dir = Path("/usr/share/AAVMF")
ovmf_code = "AAVMF_CODE.fd"
ovmf_vars = "AAVMF_VARS.fd"
qemu = "qemu-system-aarch64"
machine = "virt"
cpu = "cortex-a72"
elif target == TARGET_I686:
boot_file_name = 'bootia32.efi'
ovmf_dir = Path('/usr/share/OVMF')
ovmf_code = 'OVMF32_CODE_4M.secboot.fd'
ovmf_vars = 'OVMF32_VARS_4M.fd'
boot_file_name = "bootia32.efi"
ovmf_dir = Path("/usr/share/OVMF")
ovmf_code = "OVMF32_CODE_4M.secboot.fd"
ovmf_vars = "OVMF32_VARS_4M.fd"
# The i686 target intentionally uses 64-bit qemu; the important
# difference is that the OVMF code provides a 32-bit environment.
qemu = 'qemu-system-x86_64'
machine = 'q35'
cpu = 'qemu64'
qemu = "qemu-system-x86_64"
machine = "q35"
cpu = "qemu64"
elif target == TARGET_X86_64:
boot_file_name = 'bootx64.efi'
ovmf_dir = Path('/usr/share/OVMF')
ovmf_code = 'OVMF_CODE.fd'
ovmf_vars = 'OVMF_VARS.fd'
qemu = 'qemu-system-x86_64'
machine = 'q35'
cpu = 'qemu64'
boot_file_name = "bootx64.efi"
ovmf_dir = Path("/usr/share/OVMF")
ovmf_code = "OVMF_CODE.fd"
ovmf_vars = "OVMF_VARS.fd"
qemu = "qemu-system-x86_64"
machine = "q35"
cpu = "qemu64"
else:
raise KeyError('invalid target')
raise KeyError("invalid target")
host_artifacts = Path('/checkout/obj/build/x86_64-unknown-linux-gnu')
stage0 = host_artifacts / 'stage0/bin'
stage2 = host_artifacts / 'stage2/bin'
host_artifacts = Path("/checkout/obj/build/x86_64-unknown-linux-gnu")
stage0 = host_artifacts / "stage0/bin"
stage2 = host_artifacts / "stage2/bin"
env = dict(os.environ)
env['PATH'] = '{}:{}:{}'.format(stage2, stage0, env['PATH'])
env["PATH"] = "{}:{}:{}".format(stage2, stage0, env["PATH"])
# Copy the test create into `tmp_dir`.
test_crate = Path(tmp_dir) / 'uefi_qemu_test'
shutil.copytree('/uefi_qemu_test', test_crate)
test_crate = Path(tmp_dir) / "uefi_qemu_test"
shutil.copytree("/uefi_qemu_test", test_crate)
# Build the UEFI executable.
run('cargo',
'build',
'--manifest-path',
test_crate / 'Cargo.toml',
'--target',
run(
"cargo",
"build",
"--manifest-path",
test_crate / "Cargo.toml",
"--target",
target,
env=env)
env=env,
)
# Create a mock EFI System Partition in a subdirectory.
esp = test_crate / 'esp'
boot = esp / 'efi/boot'
esp = test_crate / "esp"
boot = esp / "efi/boot"
os.makedirs(boot, exist_ok=True)
# Copy the executable into the ESP.
src_exe_path = test_crate / 'target' / target / 'debug/uefi_qemu_test.efi'
src_exe_path = test_crate / "target" / target / "debug/uefi_qemu_test.efi"
shutil.copy(src_exe_path, boot / boot_file_name)
print(src_exe_path, boot / boot_file_name)
@ -89,37 +90,39 @@ def build_and_run(tmp_dir, target):
# Make a writable copy of the vars file. aarch64 doesn't boot
# correctly with read-only vars.
ovmf_rw_vars = Path(tmp_dir) / 'vars.fd'
ovmf_rw_vars = Path(tmp_dir) / "vars.fd"
shutil.copy(ovmf_vars, ovmf_rw_vars)
# Run the executable in QEMU and capture the output.
output = run(qemu,
'-machine',
machine,
'-cpu',
cpu,
'-display',
'none',
'-serial',
'stdio',
'-drive',
f'if=pflash,format=raw,readonly=on,file={ovmf_code}',
'-drive',
f'if=pflash,format=raw,readonly=off,file={ovmf_rw_vars}',
'-drive',
f'format=raw,file=fat:rw:{esp}',
capture=True,
check=True,
# Set a timeout to kill the VM in case something goes wrong.
timeout=60).stdout
output = run(
qemu,
"-machine",
machine,
"-cpu",
cpu,
"-display",
"none",
"-serial",
"stdio",
"-drive",
f"if=pflash,format=raw,readonly=on,file={ovmf_code}",
"-drive",
f"if=pflash,format=raw,readonly=off,file={ovmf_rw_vars}",
"-drive",
f"format=raw,file=fat:rw:{esp}",
capture=True,
check=True,
# Set a timeout to kill the VM in case something goes wrong.
timeout=60,
).stdout
if 'Hello World!' in output:
print('VM produced expected output')
if "Hello World!" in output:
print("VM produced expected output")
else:
print('unexpected VM output:')
print('---start---')
print("unexpected VM output:")
print("---start---")
print(output)
print('---end---')
print("---end---")
sys.exit(1)

View file

@ -105,6 +105,23 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
# It seems that it cannot be the same as $IMAGE_TAG, otherwise it overwrites the cache
CACHE_IMAGE_TAG=${REGISTRY}/${REGISTRY_USERNAME}/rust-ci-cache:${cksum}
# Docker build arguments.
build_args=(
"build"
"--rm"
"-t" "rust-ci"
"-f" "$dockerfile"
"$context"
)
# If the environment variable DOCKER_SCRIPT is defined,
# set the build argument SCRIPT_ARG to DOCKER_SCRIPT.
# In this way, we run the script defined in CI,
# instead of the one defined in the Dockerfile.
if [ -n "${DOCKER_SCRIPT+x}" ]; then
build_args+=("--build-arg" "SCRIPT_ARG=${DOCKER_SCRIPT}")
fi
# On non-CI jobs, we try to download a pre-built image from the rust-lang-ci
# ghcr.io registry. If it is not possible, we fall back to building the image
# locally.
@ -115,7 +132,7 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
docker tag "${IMAGE_TAG}" rust-ci
else
echo "Building local Docker image"
retry docker build --rm -t rust-ci -f "$dockerfile" "$context"
retry docker "${build_args[@]}"
fi
# On PR CI jobs, we don't have permissions to write to the registry cache,
# but we can still read from it.
@ -127,13 +144,9 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
# Build the image using registry caching backend
retry docker \
buildx \
build \
--rm \
-t rust-ci \
-f "$dockerfile" \
"${build_args[@]}" \
--cache-from type=registry,ref=${CACHE_IMAGE_TAG} \
--output=type=docker \
"$context"
--output=type=docker
# On auto/try builds, we can also write to the cache.
else
# Log into the Docker registry, so that we can read/write cache and the final image
@ -147,14 +160,10 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
# Build the image using registry caching backend
retry docker \
buildx \
build \
--rm \
-t rust-ci \
-f "$dockerfile" \
"${build_args[@]}" \
--cache-from type=registry,ref=${CACHE_IMAGE_TAG} \
--cache-to type=registry,ref=${CACHE_IMAGE_TAG},compression=zstd \
--output=type=docker \
"$context"
--output=type=docker
# Print images for debugging purposes
docker images

View file

@ -10,7 +10,7 @@ apt-get install -y --no-install-recommends \
g++ \
git \
libssl-dev \
libncurses5 \
libncurses-dev \
make \
ninja-build \
pkg-config \

View file

@ -35,6 +35,7 @@ MIRROR_BUCKET = "rust-lang-ci-mirrors"
MIRROR_BUCKET_REGION = "us-west-1"
MIRROR_BASE_DIR = "rustc/android/"
class Package:
def __init__(self, path, url, sha1, deps=None):
if deps is None:
@ -53,18 +54,25 @@ class Package:
sha1 = hashlib.sha1(f.read()).hexdigest()
if sha1 != self.sha1:
raise RuntimeError(
"hash mismatch for package " + self.path + ": " +
sha1 + " vs " + self.sha1 + " (known good)"
"hash mismatch for package "
+ self.path
+ ": "
+ sha1
+ " vs "
+ self.sha1
+ " (known good)"
)
return file
def __repr__(self):
return "<Package "+self.path+" at "+self.url+" (sha1="+self.sha1+")"
return "<Package " + self.path + " at " + self.url + " (sha1=" + self.sha1 + ")"
def fetch_url(url):
page = urllib.request.urlopen(url)
return page.read()
def fetch_repository(base, repo_url):
packages = {}
root = ET.fromstring(fetch_url(base + repo_url))
@ -92,12 +100,14 @@ def fetch_repository(base, repo_url):
return packages
def fetch_repositories():
packages = {}
for repo in REPOSITORIES:
packages.update(fetch_repository(BASE_REPOSITORY, repo))
return packages
class Lockfile:
def __init__(self, path):
self.path = path
@ -123,6 +133,7 @@ class Lockfile:
for package in packages:
f.write(package.path + " " + package.url + " " + package.sha1 + "\n")
def cli_add_to_lockfile(args):
lockfile = Lockfile(args.lockfile)
packages = fetch_repositories()
@ -130,28 +141,49 @@ def cli_add_to_lockfile(args):
lockfile.add(packages, package)
lockfile.save()
def cli_update_mirror(args):
lockfile = Lockfile(args.lockfile)
for package in lockfile.packages.values():
path = package.download(BASE_REPOSITORY)
subprocess.run([
"aws", "s3", "mv", path,
"s3://" + MIRROR_BUCKET + "/" + MIRROR_BASE_DIR + package.url,
"--profile=" + args.awscli_profile,
], check=True)
subprocess.run(
[
"aws",
"s3",
"mv",
path,
"s3://" + MIRROR_BUCKET + "/" + MIRROR_BASE_DIR + package.url,
"--profile=" + args.awscli_profile,
],
check=True,
)
def cli_install(args):
lockfile = Lockfile(args.lockfile)
for package in lockfile.packages.values():
# Download the file from the mirror into a temp file
url = "https://" + MIRROR_BUCKET + ".s3-" + MIRROR_BUCKET_REGION + \
".amazonaws.com/" + MIRROR_BASE_DIR
url = (
"https://"
+ MIRROR_BUCKET
+ ".s3-"
+ MIRROR_BUCKET_REGION
+ ".amazonaws.com/"
+ MIRROR_BASE_DIR
)
downloaded = package.download(url)
# Extract the file in a temporary directory
extract_dir = tempfile.mkdtemp()
subprocess.run([
"unzip", "-q", downloaded, "-d", extract_dir,
], check=True)
subprocess.run(
[
"unzip",
"-q",
downloaded,
"-d",
extract_dir,
],
check=True,
)
# Figure out the prefix used in the zip
subdirs = [d for d in os.listdir(extract_dir) if not d.startswith(".")]
if len(subdirs) != 1:
@ -162,6 +194,7 @@ def cli_install(args):
os.rename(os.path.join(extract_dir, subdirs[0]), dest)
os.unlink(downloaded)
def cli():
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
@ -187,5 +220,6 @@ def cli():
exit(1)
args.func(args)
if __name__ == "__main__":
cli()

View file

@ -588,7 +588,7 @@ class TestEnvironment:
"--repo-path",
self.repo_dir(),
"--repository",
self.TEST_REPO_NAME
self.TEST_REPO_NAME,
],
env=ffx_env,
stdout_handler=self.subprocess_logger.debug,
@ -619,9 +619,7 @@ class TestEnvironment:
# `facet` statement required for TCP testing via
# protocol `fuchsia.posix.socket.Provider`. See
# https://fuchsia.dev/fuchsia-src/development/testing/components/test_runner_framework?hl=en#legacy_non-hermetic_tests
CML_TEMPLATE: ClassVar[
str
] = """
CML_TEMPLATE: ClassVar[str] = """
{{
program: {{
runner: "elf_test_runner",
@ -994,7 +992,7 @@ class TestEnvironment:
"repository",
"server",
"stop",
self.TEST_REPO_NAME
self.TEST_REPO_NAME,
],
env=self.ffx_cmd_env(),
stdout_handler=self.subprocess_logger.debug,

View file

@ -2,7 +2,7 @@
set -euo pipefail
LINUX_VERSION=28e848386b92645f93b9f2fdba5882c3ca7fb3e2
LINUX_VERSION=v6.13-rc1
# Build rustc, rustdoc, cargo, clippy-driver and rustfmt
../x.py build --stage 2 library rustdoc clippy rustfmt
@ -64,7 +64,7 @@ make -C linux LLVM=1 -j$(($(nproc) + 1)) \
BUILD_TARGETS="
samples/rust/rust_minimal.o
samples/rust/rust_print.o
samples/rust/rust_print_main.o
drivers/net/phy/ax88796b_rust.o
rust/doctests_kernel_generated.o
"

View file

@ -7,6 +7,7 @@ be executed on CI.
It reads job definitions from `src/ci/github-actions/jobs.yml`
and filters them based on the event that happened on CI.
"""
import dataclasses
import json
import logging
@ -94,7 +95,7 @@ def find_run_type(ctx: GitHubCtx) -> Optional[WorkflowRunType]:
try_build = ctx.ref in (
"refs/heads/try",
"refs/heads/try-perf",
"refs/heads/automation/bors/try"
"refs/heads/automation/bors/try",
)
# Unrolled branch from a rollup for testing perf
@ -135,11 +136,15 @@ def calculate_jobs(run_type: WorkflowRunType, job_data: Dict[str, Any]) -> List[
continue
jobs.append(job[0])
if unknown_jobs:
raise Exception(f"Custom job(s) `{unknown_jobs}` not found in auto jobs")
raise Exception(
f"Custom job(s) `{unknown_jobs}` not found in auto jobs"
)
return add_base_env(name_jobs(jobs, "try"), job_data["envs"]["try"])
elif isinstance(run_type, AutoRunType):
return add_base_env(name_jobs(job_data["auto"], "auto"), job_data["envs"]["auto"])
return add_base_env(
name_jobs(job_data["auto"], "auto"), job_data["envs"]["auto"]
)
return []
@ -161,7 +166,7 @@ def get_github_ctx() -> GitHubCtx:
event_name=event_name,
ref=os.environ["GITHUB_REF"],
repository=os.environ["GITHUB_REPOSITORY"],
commit_message=commit_message
commit_message=commit_message,
)

View file

@ -43,7 +43,7 @@ runners:
os: windows-2022-16core-64gb
<<: *base-job
- &job-aarch64-linux
- &job-linux-8c-aarch64
os: ubuntu-22.04-arm64-8core-32gb
envs:
@ -58,6 +58,22 @@ envs:
NO_DEBUG_ASSERTIONS: 1
NO_OVERFLOW_CHECKS: 1
# Different set of tests to run tests in parallel in multiple jobs.
stage_2_test_set1: &stage_2_test_set1
DOCKER_SCRIPT: >-
python3 ../x.py --stage 2 test
--skip compiler
--skip src
stage_2_test_set2: &stage_2_test_set2
DOCKER_SCRIPT: >-
python3 ../x.py --stage 2 test
--skip tests
--skip coverage-map
--skip coverage-run
--skip library
--skip tidyselftest
production:
&production
DEPLOY_BUCKET: rust-lang-ci2
@ -123,10 +139,10 @@ auto:
#############################
- image: aarch64-gnu
<<: *job-aarch64-linux
<<: *job-linux-8c-aarch64
- image: aarch64-gnu-debug
<<: *job-aarch64-linux
<<: *job-linux-8c-aarch64
- image: arm-android
<<: *job-linux-4c
@ -143,7 +159,7 @@ auto:
<<: *job-linux-4c
- image: dist-arm-linux
<<: *job-linux-8c
<<: *job-linux-8c-aarch64
- image: dist-armhf-linux
<<: *job-linux-4c
@ -212,11 +228,42 @@ auto:
- image: dist-x86_64-netbsd
<<: *job-linux-4c
- image: i686-gnu
<<: *job-linux-8c
# The i686-gnu job is split into multiple jobs to run tests in parallel.
# i686-gnu-1 skips tests that run in i686-gnu-2.
- image: i686-gnu-1
env:
IMAGE: i686-gnu
<<: *stage_2_test_set1
<<: *job-linux-4c
- image: i686-gnu-nopt
<<: *job-linux-8c
# Skip tests that run in i686-gnu-1
- image: i686-gnu-2
env:
IMAGE: i686-gnu
<<: *stage_2_test_set2
<<: *job-linux-4c
# The i686-gnu-nopt job is split into multiple jobs to run tests in parallel.
# i686-gnu-nopt-1 skips tests that run in i686-gnu-nopt-2
- image: i686-gnu-nopt-1
env:
IMAGE: i686-gnu-nopt
<<: *stage_2_test_set1
<<: *job-linux-4c
# Skip tests that run in i686-gnu-nopt-1
- image: i686-gnu-nopt-2
env:
IMAGE: i686-gnu-nopt
DOCKER_SCRIPT: >-
python3 ../x.py test --stage 0 --config /config/nopt-std-config.toml library/std &&
python3 ../x.py --stage 2 test
--skip tests
--skip coverage-map
--skip coverage-run
--skip library
--skip tidyselftest
<<: *job-linux-4c
- image: mingw-check
<<: *job-linux-4c
@ -338,6 +385,7 @@ auto:
--set rust.jemalloc
--set llvm.ninja=false
--set rust.lto=thin
--set rust.codegen-units=1
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
SELECT_XCODE: /Applications/Xcode_15.4.app
USE_XCODE_CLANG: 1
@ -439,14 +487,24 @@ auto:
NO_DOWNLOAD_CI_LLVM: 1
<<: *job-windows-8c
- image: x86_64-mingw
# x86_64-mingw is split into two jobs to run tests in parallel.
- image: x86_64-mingw-1
env:
SCRIPT: make ci-mingw
SCRIPT: make ci-mingw-x
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu
# We are intentionally allowing an old toolchain on this builder (and that's
# incompatible with LLVM downloads today).
NO_DOWNLOAD_CI_LLVM: 1
<<: *job-windows-8c
<<: *job-windows
- image: x86_64-mingw-2
env:
SCRIPT: make ci-mingw-bootstrap
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu
# We are intentionally allowing an old toolchain on this builder (and that's
# incompatible with LLVM downloads today).
NO_DOWNLOAD_CI_LLVM: 1
<<: *job-windows
- image: dist-x86_64-msvc
env:

View file

@ -19,6 +19,7 @@ $ python3 upload-build-metrics.py <path-to-CPU-usage-CSV>
`path-to-CPU-usage-CSV` is a path to a CSV generated by the `src/ci/cpu-usage-over-time.py` script.
"""
import argparse
import csv
import os
@ -31,7 +32,7 @@ from typing import List
def load_cpu_usage(path: Path) -> List[float]:
usage = []
with open(path) as f:
reader = csv.reader(f, delimiter=',')
reader = csv.reader(f, delimiter=",")
for row in reader:
# The log might contain incomplete rows or some Python exception
if len(row) == 2:
@ -50,25 +51,21 @@ def upload_datadog_measure(name: str, value: float):
print(f"Metric {name}: {value:.4f}")
datadog_cmd = "datadog-ci"
if os.getenv("GITHUB_ACTIONS") is not None and sys.platform.lower().startswith("win"):
if os.getenv("GITHUB_ACTIONS") is not None and sys.platform.lower().startswith(
"win"
):
# Due to weird interaction of MSYS2 and Python, we need to use an absolute path,
# and also specify the ".cmd" at the end. See https://github.com/rust-lang/rust/pull/125771.
datadog_cmd = "C:\\npm\\prefix\\datadog-ci.cmd"
subprocess.run([
datadog_cmd,
"measure",
"--level", "job",
"--measures", f"{name}:{value}"
],
check=False
subprocess.run(
[datadog_cmd, "measure", "--level", "job", "--measures", f"{name}:{value}"],
check=False,
)
if __name__ == "__main__":
parser = argparse.ArgumentParser(
prog="DataDog metric uploader"
)
parser = argparse.ArgumentParser(prog="DataDog metric uploader")
parser.add_argument("cpu-usage-history-csv")
args = parser.parse_args()

View file

@ -53,7 +53,8 @@ function isLinux {
}
function isKnownToBeMingwBuild {
isGitHubActions && [[ "${CI_JOB_NAME}" == *mingw ]]
# CI_JOB_NAME must end with "mingw" and optionally `-N` to be considered a MinGW build.
isGitHubActions && [[ "${CI_JOB_NAME}" =~ mingw(-[0-9]+)?$ ]]
}
function isCiBranch {

@ -1 +1 @@
Subproject commit e16dd73690a6cc3ecdc5f5d94bbc3ce158a42e16
Subproject commit 9900d976bbfecf4e8124da54351a9ad85ee3c7f3

@ -1 +1 @@
Subproject commit f48b0e842a3911c63240e955d042089e9e0894c7
Subproject commit 128669297c8a7fdf771042eaec18b8adfaeaf0cd

@ -1 +1 @@
Subproject commit 5c86c739ec71b8bc839310ff47fa94e94635bba9
Subproject commit ede56d1bbe132bac476b5029cd6d7508ca9572e9

@ -1 +1 @@
Subproject commit 787b4166ccc67bd8f72a6e3ef6685ce9ce82909a
Subproject commit b21d99b770f9aceb0810c843847c52f86f45d2ed

View file

@ -344,15 +344,15 @@ target | std | host | notes
[`powerpc-wrs-vxworks-spe`](platform-support/vxworks.md) | ✓ | |
[`powerpc-wrs-vxworks`](platform-support/vxworks.md) | ✓ | |
`powerpc64-unknown-freebsd` | ✓ | ✓ | PPC64 FreeBSD (ELFv1 and ELFv2)
`powerpc64le-unknown-freebsd` | | | PPC64LE FreeBSD
`powerpc-unknown-freebsd` | | | PowerPC FreeBSD
`powerpc64le-unknown-freebsd` | ✓ | ✓ | PPC64LE FreeBSD
`powerpc-unknown-freebsd` | ? | | PowerPC FreeBSD
`powerpc64-unknown-linux-musl` | ? | | 64-bit PowerPC Linux with musl 1.2.3
[`powerpc64-wrs-vxworks`](platform-support/vxworks.md) | ✓ | |
`powerpc64le-unknown-linux-musl` | ? | | 64-bit PowerPC Linux with musl 1.2.3, Little Endian
[`powerpc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/powerpc64
[`powerpc64-ibm-aix`](platform-support/aix.md) | ? | | 64-bit AIX (7.2 and newer)
`riscv32gc-unknown-linux-gnu` | | | RISC-V Linux (kernel 5.4, glibc 2.33)
`riscv32gc-unknown-linux-musl` | | | RISC-V Linux (kernel 5.4, musl 1.2.3 + RISCV32 support patches)
`riscv32gc-unknown-linux-gnu` | | | RISC-V Linux (kernel 5.4, glibc 2.33)
`riscv32gc-unknown-linux-musl` | ? | | RISC-V Linux (kernel 5.4, musl 1.2.3 + RISCV32 support patches)
[`riscv32im-risc0-zkvm-elf`](platform-support/riscv32im-risc0-zkvm-elf.md) | ? | | RISC Zero's zero-knowledge Virtual Machine (RV32IM ISA)
[`riscv32ima-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | | Bare RISC-V (RV32IMA ISA)
[`riscv32imac-unknown-xous-elf`](platform-support/riscv32imac-unknown-xous-elf.md) | ? | | RISC-V Xous (RV32IMAC ISA)
@ -361,13 +361,13 @@ target | std | host | notes
[`riscv32imafc-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF
[`riscv32-wrs-vxworks`](platform-support/vxworks.md) | ✓ | |
[`riscv64gc-unknown-hermit`](platform-support/hermit.md) | ✓ | | RISC-V Hermit
`riscv64gc-unknown-freebsd` | | | RISC-V FreeBSD
`riscv64gc-unknown-fuchsia` | | | RISC-V Fuchsia
`riscv64gc-unknown-freebsd` | ? | | RISC-V FreeBSD
`riscv64gc-unknown-fuchsia` | ? | | RISC-V Fuchsia
[`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | RISC-V NetBSD
[`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64
[`riscv64-linux-android`](platform-support/android.md) | | | RISC-V 64-bit Android
[`riscv64-linux-android`](platform-support/android.md) | ? | | RISC-V 64-bit Android
[`riscv64-wrs-vxworks`](platform-support/vxworks.md) | ✓ | |
[`s390x-unknown-linux-musl`](platform-support/s390x-unknown-linux-musl.md) | | | S390x Linux (kernel 3.2, musl 1.2.3)
[`s390x-unknown-linux-musl`](platform-support/s390x-unknown-linux-musl.md) | | | S390x Linux (kernel 3.2, musl 1.2.3)
`sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux
[`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * | | Bare 32-bit SPARC V7+
[`sparc64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/sparc64

View file

@ -16,7 +16,7 @@ BE8 architecture is the default big-endian architecture for Arm since [Armv6](ht
The target is cross-compiled. This target supports `std` in the normal way (indeed only nominal changes are required from the standard Arm configuration).
## Target definition
The target definition can be seen [here](https://github.com/rust-lang/rust/tree/master/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs). In particular, it should be noted that the `features` specify that this target is built for the Armv8 core. Though this can likely be modified as required.
The target definition can be seen [here](https://github.com/rust-lang/rust/blob/master/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs). In particular, it should be noted that the `features` specify that this target is built for the Armv8 core. Though this can likely be modified as required.
## Building the target
Because it is Tier 3, rust does not yet ship pre-compiled artifacts for this target.

View file

@ -64,6 +64,22 @@ There are no special requirements for testing and running the target.
For testing cross builds on the host, please refer to the "Cross-compilation
toolchains and C code" section below.
If you want to do native testing but do not have your own s390x
machine, there are several options how to get access to one:
* The [IBM LinuxONE Community Cloud][cloud-community] provides a
self-service portal where you can create s390x virtual machine
instances. These are intended for temporary use (limited to 120 days).
* The [IBM LinuxONE Open Source Cloud][cloud-opensource] provides
permanent access to s390x machines. This requires approval by IBM,
which will normally be granted if you're planning to use the machine
to work on an open-source project that is relevant to the IBM Z
ecosystem - the Rust compiler would certainly qualify.
[cloud-community]: https://linuxone.cloud.marist.edu/
[cloud-opensource]: https://community.ibm.com/zsystems/form/l1cc-oss-vm-request/
## Cross-compilation toolchains and C code
Rust code built using the target is compatible with C code compiled with

View file

@ -47,6 +47,10 @@ It can be enabled using:
#![deny(rustdoc::missing_doc_code_examples)]
```
It is not emitted for items that cannot be instantiated/called such as fields, variants, modules,
associated trait/impl items, impl blocks, statics and constants.
It is also not emitted for foreign items, aliases, extern crates and imports.
## Extensions to the `#[doc]` attribute
These features operate by extending the `#[doc]` attribute, and thus can be caught by the compiler

View file

@ -0,0 +1,7 @@
# `debug-info-type-line-numbers`
---
This option causes additional type and line information to be emitted in debug
info to provide richer information to debuggers. This is currently off by
default as it causes some compilation scenarios to be noticeably slower.

View file

@ -0,0 +1,23 @@
# `randomize-layout`
The tracking issue for this feature is: [#106764](https://github.com/rust-lang/rust/issues/106764).
------------------------
The `-Zrandomize-layout` flag changes the layout algorithm for `repr(Rust)` types defined in the current crate from its normal
optimization goals to pseudorandomly rearranging fields within the degrees of freedom provided by the largely unspecified
default representation. This also affects type sizes and padding.
Downstream intantiations of generic types defined in a crate with randomization enabled will also be randomized.
It can be used to find unsafe code that accidentally relies on unspecified behavior.
Randomization is not guaranteed to use a different permutation for each compilation session.
`-Zlayout-seed=<u64>` can be used to supply additional entropy.
Randomization only approximates the intended freedom of repr(Rust). Sometimes two distinct types may still consistently
result in the same layout due to limitations of the current implementation. Randomization may become
more aggressive over time as our coverage of the available degrees of freedoms improves.
Corollary: Randomization is not a safety oracle. Two struct layouts being observably the same under different layout seeds
on the current compiler version does not guarantee that future compiler versions won't give them distinct layouts.
Randomization may also become less aggressive in the future if additional guarantees get added to the default layout.

View file

@ -0,0 +1,15 @@
# `reg-struct-return`
The tracking issue for this feature is: https://github.com/rust-lang/rust/issues/116973.
------------------------
Option -Zreg-struct-return causes the compiler to return small structs in registers
instead of on the stack for extern "C"-like functions.
It is UNSOUND to link together crates that use different values for this flag.
It is only supported on `x86`.
It is equivalent to [Clang]'s and [GCC]'s `-freg-struct-return`.
[Clang]: https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-freg-struct-return
[GCC]: https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-freg-struct-return

View file

@ -34,7 +34,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
| PowerPC | `reg` | `r0`, `r[3-12]`, `r[14-28]` | `r` |
| PowerPC | `reg_nonzero` | `r[3-12]`, `r[14-28]` | `b` |
| PowerPC | `freg` | `f[0-31]` | `f` |
| PowerPC | `vreg` | `v[0-31]` | Only clobbers |
| PowerPC | `vreg` | `v[0-31]` | `v` |
| PowerPC | `cr` | `cr[0-7]`, `cr` | Only clobbers |
| PowerPC | `xer` | `xer` | Only clobbers |
| wasm32 | `local` | None\* | `r` |
@ -75,7 +75,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
| PowerPC | `reg` | None | `i8`, `i16`, `i32`, `i64` (powerpc64 only) |
| PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32`, `i64` (powerpc64 only) |
| PowerPC | `freg` | None | `f32`, `f64` |
| PowerPC | `vreg` | N/A | Only clobbers |
| PowerPC | `vreg` | `altivec` | `i8x16`, `i16x8`, `i32x4`, `f32x4` |
| PowerPC | `vreg` | `vsx` | `f32`, `f64`, `i64x2`, `f64x2` |
| PowerPC | `cr` | N/A | Only clobbers |
| PowerPC | `xer` | N/A | Only clobbers |
| wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` |
@ -181,6 +182,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
| PowerPC | `reg` | None | `0` | None |
| PowerPC | `reg_nonzero` | None | `3` | None |
| PowerPC | `freg` | None | `0` | None |
| PowerPC | `vreg` | None | `0` | None |
| SPARC | `reg` | None | `%o0` | None |
| CSKY | `reg` | None | `r0` | None |
| CSKY | `freg` | None | `f0` | None |

View file

@ -1,10 +0,0 @@
# `extended_varargs_abi_support`
The tracking issue for this feature is: [#100189]
[#100189]: https://github.com/rust-lang/rust/issues/100189
------------------------
This feature adds the possibility of using `sysv64`, `win64` or `efiapi` calling
conventions on functions with varargs.

View file

@ -13,6 +13,7 @@ i.e., within 0.5 ULP of the true value.
Adapted from Daniel Lemire's fast_float ``table_generation.py``,
available here: <https://github.com/fastfloat/fast_float/blob/main/script/table_generation.py>.
"""
from __future__ import print_function
from math import ceil, floor, log
from collections import deque
@ -34,6 +35,7 @@ STATIC_WARNING = """
// the final binary.
"""
def main():
min_exp = minimum_exponent(10)
max_exp = maximum_exponent(10)
@ -41,10 +43,10 @@ def main():
print(HEADER.strip())
print()
print('pub const SMALLEST_POWER_OF_FIVE: i32 = {};'.format(min_exp))
print('pub const LARGEST_POWER_OF_FIVE: i32 = {};'.format(max_exp))
print('pub const N_POWERS_OF_FIVE: usize = ', end='')
print('(LARGEST_POWER_OF_FIVE - SMALLEST_POWER_OF_FIVE + 1) as usize;')
print("pub const SMALLEST_POWER_OF_FIVE: i32 = {};".format(min_exp))
print("pub const LARGEST_POWER_OF_FIVE: i32 = {};".format(max_exp))
print("pub const N_POWERS_OF_FIVE: usize = ", end="")
print("(LARGEST_POWER_OF_FIVE - SMALLEST_POWER_OF_FIVE + 1) as usize;")
print()
print_proper_powers(min_exp, max_exp, bias)
@ -54,7 +56,7 @@ def minimum_exponent(base):
def maximum_exponent(base):
return floor(log(1.7976931348623157e+308, base))
return floor(log(1.7976931348623157e308, base))
def print_proper_powers(min_exp, max_exp, bias):
@ -64,46 +66,46 @@ def print_proper_powers(min_exp, max_exp, bias):
# 2^(2b)/(5^q) with b=64 + int(math.ceil(log2(5^q)))
powers = []
for q in range(min_exp, 0):
power5 = 5 ** -q
power5 = 5**-q
z = 0
while (1 << z) < power5:
z += 1
if q >= -27:
b = z + 127
c = 2 ** b // power5 + 1
c = 2**b // power5 + 1
powers.append((c, q))
else:
b = 2 * z + 2 * 64
c = 2 ** b // power5 + 1
c = 2**b // power5 + 1
# truncate
while c >= (1<<128):
while c >= (1 << 128):
c //= 2
powers.append((c, q))
# Add positive exponents
for q in range(0, max_exp + 1):
power5 = 5 ** q
power5 = 5**q
# move the most significant bit in position
while power5 < (1<<127):
while power5 < (1 << 127):
power5 *= 2
# *truncate*
while power5 >= (1<<128):
while power5 >= (1 << 128):
power5 //= 2
powers.append((power5, q))
# Print the powers.
print(STATIC_WARNING.strip())
print('#[rustfmt::skip]')
typ = '[(u64, u64); N_POWERS_OF_FIVE]'
print('pub static POWER_OF_FIVE_128: {} = ['.format(typ))
print("#[rustfmt::skip]")
typ = "[(u64, u64); N_POWERS_OF_FIVE]"
print("pub static POWER_OF_FIVE_128: {} = [".format(typ))
for c, exp in powers:
hi = '0x{:x}'.format(c // (1 << 64))
lo = '0x{:x}'.format(c % (1 << 64))
value = ' ({}, {}), '.format(hi, lo)
comment = '// {}^{}'.format(5, exp)
print(value.ljust(46, ' ') + comment)
print('];')
hi = "0x{:x}".format(c // (1 << 64))
lo = "0x{:x}".format(c % (1 << 64))
value = " ({}, {}), ".format(hi, lo)
comment = "// {}^{}".format(5, exp)
print(value.ljust(46, " ") + comment)
print("];")
if __name__ == '__main__':
if __name__ == "__main__":
main()

View file

@ -1,6 +1,7 @@
# Add this folder to the python sys path; GDB Python-interpreter will now find modules in this path
import sys
from os import path
self_dir = path.dirname(path.realpath(__file__))
sys.path.append(self_dir)

View file

@ -6,8 +6,11 @@ from gdb_providers import *
from rust_types import *
_gdb_version_matched = re.search('([0-9]+)\\.([0-9]+)', gdb.VERSION)
gdb_version = [int(num) for num in _gdb_version_matched.groups()] if _gdb_version_matched else []
_gdb_version_matched = re.search("([0-9]+)\\.([0-9]+)", gdb.VERSION)
gdb_version = (
[int(num) for num in _gdb_version_matched.groups()] if _gdb_version_matched else []
)
def register_printers(objfile):
objfile.pretty_printers.append(printer)

View file

@ -21,7 +21,7 @@ def unwrap_unique_or_non_null(unique_or_nonnull):
# GDB 14 has a tag class that indicates that extension methods are ok
# to call. Use of this tag only requires that printers hide local
# attributes and methods by prefixing them with "_".
if hasattr(gdb, 'ValuePrinter'):
if hasattr(gdb, "ValuePrinter"):
printer_base = gdb.ValuePrinter
else:
printer_base = object
@ -98,7 +98,7 @@ class StdStrProvider(printer_base):
def _enumerate_array_elements(element_ptrs):
for (i, element_ptr) in enumerate(element_ptrs):
for i, element_ptr in enumerate(element_ptrs):
key = "[{}]".format(i)
element = element_ptr.dereference()
@ -173,7 +173,8 @@ class StdVecDequeProvider(printer_base):
def children(self):
return _enumerate_array_elements(
(self._data_ptr + ((self._head + index) % self._cap)) for index in xrange(self._size)
(self._data_ptr + ((self._head + index) % self._cap))
for index in xrange(self._size)
)
@staticmethod
@ -270,7 +271,9 @@ def children_of_btree_map(map):
# Yields each key/value pair in the node and in any child nodes.
def children_of_node(node_ptr, height):
def cast_to_internal(node):
internal_type_name = node.type.target().name.replace("LeafNode", "InternalNode", 1)
internal_type_name = node.type.target().name.replace(
"LeafNode", "InternalNode", 1
)
internal_type = gdb.lookup_type(internal_type_name)
return node.cast(internal_type.pointer())
@ -293,8 +296,16 @@ def children_of_btree_map(map):
# Avoid "Cannot perform pointer math on incomplete type" on zero-sized arrays.
key_type_size = keys.type.sizeof
val_type_size = vals.type.sizeof
key = keys[i]["value"]["value"] if key_type_size > 0 else gdb.parse_and_eval("()")
val = vals[i]["value"]["value"] if val_type_size > 0 else gdb.parse_and_eval("()")
key = (
keys[i]["value"]["value"]
if key_type_size > 0
else gdb.parse_and_eval("()")
)
val = (
vals[i]["value"]["value"]
if val_type_size > 0
else gdb.parse_and_eval("()")
)
yield key, val
if map["length"] > 0:
@ -352,7 +363,7 @@ class StdOldHashMapProvider(printer_base):
self._hashes = self._table["hashes"]
self._hash_uint_type = self._hashes.type
self._hash_uint_size = self._hashes.type.sizeof
self._modulo = 2 ** self._hash_uint_size
self._modulo = 2**self._hash_uint_size
self._data_ptr = self._hashes[ZERO_FIELD]["pointer"]
self._capacity_mask = int(self._table["capacity_mask"])
@ -382,8 +393,14 @@ class StdOldHashMapProvider(printer_base):
hashes = self._hash_uint_size * self._capacity
align = self._pair_type_size
len_rounded_up = (((((hashes + align) % self._modulo - 1) % self._modulo) & ~(
(align - 1) % self._modulo)) % self._modulo - hashes) % self._modulo
len_rounded_up = (
(
(((hashes + align) % self._modulo - 1) % self._modulo)
& ~((align - 1) % self._modulo)
)
% self._modulo
- hashes
) % self._modulo
pairs_offset = hashes + len_rounded_up
pairs_start = gdb.Value(start + pairs_offset).cast(self._pair_type.pointer())

View file

@ -12,7 +12,8 @@ import os
import stat
TEST_DIR = os.path.abspath(
os.path.join(os.path.dirname(__file__), '../test/ui/derives/'))
os.path.join(os.path.dirname(__file__), "../test/ui/derives/")
)
TEMPLATE = """\
// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
@ -56,28 +57,33 @@ ENUM_TUPLE, ENUM_STRUCT, STRUCT_FIELDS, STRUCT_TUPLE = range(4)
def create_test_case(type, trait, super_traits, error_count):
string = [ENUM_STRING, ENUM_STRUCT_VARIANT_STRING, STRUCT_STRING, STRUCT_TUPLE_STRING][type]
all_traits = ','.join([trait] + super_traits)
super_traits = ','.join(super_traits)
error_deriving = '#[derive(%s)]' % super_traits if super_traits else ''
string = [
ENUM_STRING,
ENUM_STRUCT_VARIANT_STRING,
STRUCT_STRING,
STRUCT_TUPLE_STRING,
][type]
all_traits = ",".join([trait] + super_traits)
super_traits = ",".join(super_traits)
error_deriving = "#[derive(%s)]" % super_traits if super_traits else ""
errors = '\n'.join('//~%s ERROR' % ('^' * n) for n in range(error_count))
errors = "\n".join("//~%s ERROR" % ("^" * n) for n in range(error_count))
code = string.format(traits=all_traits, errors=errors)
return TEMPLATE.format(error_deriving=error_deriving, code=code)
def write_file(name, string):
test_file = os.path.join(TEST_DIR, 'derives-span-%s.rs' % name)
test_file = os.path.join(TEST_DIR, "derives-span-%s.rs" % name)
# set write permission if file exists, so it can be changed
if os.path.exists(test_file):
os.chmod(test_file, stat.S_IWUSR)
with open(test_file, 'w') as f:
with open(test_file, "w") as f:
f.write(string)
# mark file read-only
os.chmod(test_file, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH)
os.chmod(test_file, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
ENUM = 1
@ -85,29 +91,31 @@ STRUCT = 2
ALL = STRUCT | ENUM
traits = {
'Default': (STRUCT, [], 1),
'FromPrimitive': (0, [], 0), # only works for C-like enums
'Decodable': (0, [], 0), # FIXME: quoting gives horrible spans
'Encodable': (0, [], 0), # FIXME: quoting gives horrible spans
"Default": (STRUCT, [], 1),
"FromPrimitive": (0, [], 0), # only works for C-like enums
"Decodable": (0, [], 0), # FIXME: quoting gives horrible spans
"Encodable": (0, [], 0), # FIXME: quoting gives horrible spans
}
for (trait, supers, errs) in [('Clone', [], 1),
('PartialEq', [], 2),
('PartialOrd', ['PartialEq'], 1),
('Eq', ['PartialEq'], 1),
('Ord', ['Eq', 'PartialOrd', 'PartialEq'], 1),
('Debug', [], 1),
('Hash', [], 1)]:
for trait, supers, errs in [
("Clone", [], 1),
("PartialEq", [], 2),
("PartialOrd", ["PartialEq"], 1),
("Eq", ["PartialEq"], 1),
("Ord", ["Eq", "PartialOrd", "PartialEq"], 1),
("Debug", [], 1),
("Hash", [], 1),
]:
traits[trait] = (ALL, supers, errs)
for (trait, (types, super_traits, error_count)) in traits.items():
for trait, (types, super_traits, error_count) in traits.items():
def mk(ty, t=trait, st=super_traits, ec=error_count):
return create_test_case(ty, t, st, ec)
if types & ENUM:
write_file(trait + '-enum', mk(ENUM_TUPLE))
write_file(trait + '-enum-struct-variant', mk(ENUM_STRUCT))
write_file(trait + "-enum", mk(ENUM_TUPLE))
write_file(trait + "-enum-struct-variant", mk(ENUM_STRUCT))
if types & STRUCT:
write_file(trait + '-struct', mk(STRUCT_FIELDS))
write_file(trait + '-tuple-struct', mk(STRUCT_TUPLE))
write_file(trait + "-struct", mk(STRUCT_FIELDS))
write_file(trait + "-tuple-struct", mk(STRUCT_TUPLE))

View file

@ -22,18 +22,16 @@ fn main() {
}
"""
test_dir = os.path.abspath(
os.path.join(os.path.dirname(__file__), '../test/ui/parser')
)
test_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "../test/ui/parser"))
for kw in sys.argv[1:]:
test_file = os.path.join(test_dir, 'keyword-%s-as-identifier.rs' % kw)
test_file = os.path.join(test_dir, "keyword-%s-as-identifier.rs" % kw)
# set write permission if file exists, so it can be changed
if os.path.exists(test_file):
os.chmod(test_file, stat.S_IWUSR)
with open(test_file, 'wt') as f:
with open(test_file, "wt") as f:
f.write(template % (kw, kw, kw))
# mark file read-only

View file

@ -127,6 +127,7 @@ import os.path
import re
import shlex
from collections import namedtuple
try:
from html.parser import HTMLParser
except ImportError:
@ -142,12 +143,28 @@ except ImportError:
from htmlentitydefs import name2codepoint
# "void elements" (no closing tag) from the HTML Standard section 12.1.2
VOID_ELEMENTS = {'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen',
'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'}
VOID_ELEMENTS = {
"area",
"base",
"br",
"col",
"embed",
"hr",
"img",
"input",
"keygen",
"link",
"menuitem",
"meta",
"param",
"source",
"track",
"wbr",
}
# Python 2 -> 3 compatibility
try:
unichr # noqa: B018 FIXME: py2
unichr # noqa: B018 FIXME: py2
except NameError:
unichr = chr
@ -158,18 +175,20 @@ channel = os.environ["DOC_RUST_LANG_ORG_CHANNEL"]
rust_test_path = None
bless = None
class CustomHTMLParser(HTMLParser):
"""simplified HTML parser.
this is possible because we are dealing with very regular HTML from
rustdoc; we only have to deal with i) void elements and ii) empty
attributes."""
def __init__(self, target=None):
HTMLParser.__init__(self)
self.__builder = target or ET.TreeBuilder()
def handle_starttag(self, tag, attrs):
attrs = {k: v or '' for k, v in attrs}
attrs = {k: v or "" for k, v in attrs}
self.__builder.start(tag, attrs)
if tag in VOID_ELEMENTS:
self.__builder.end(tag)
@ -178,7 +197,7 @@ class CustomHTMLParser(HTMLParser):
self.__builder.end(tag)
def handle_startendtag(self, tag, attrs):
attrs = {k: v or '' for k, v in attrs}
attrs = {k: v or "" for k, v in attrs}
self.__builder.start(tag, attrs)
self.__builder.end(tag)
@ -189,7 +208,7 @@ class CustomHTMLParser(HTMLParser):
self.__builder.data(unichr(name2codepoint[name]))
def handle_charref(self, name):
code = int(name[1:], 16) if name.startswith(('x', 'X')) else int(name, 10)
code = int(name[1:], 16) if name.startswith(("x", "X")) else int(name, 10)
self.__builder.data(unichr(code))
def close(self):
@ -197,7 +216,7 @@ class CustomHTMLParser(HTMLParser):
return self.__builder.close()
Command = namedtuple('Command', 'negated cmd args lineno context')
Command = namedtuple("Command", "negated cmd args lineno context")
class FailedCheck(Exception):
@ -216,17 +235,17 @@ def concat_multi_lines(f):
concatenated."""
lastline = None # set to the last line when the last line has a backslash
firstlineno = None
catenated = ''
catenated = ""
for lineno, line in enumerate(f):
line = line.rstrip('\r\n')
line = line.rstrip("\r\n")
# strip the common prefix from the current line if needed
if lastline is not None:
common_prefix = os.path.commonprefix([line, lastline])
line = line[len(common_prefix):].lstrip()
line = line[len(common_prefix) :].lstrip()
firstlineno = firstlineno or lineno
if line.endswith('\\'):
if line.endswith("\\"):
if lastline is None:
lastline = line[:-1]
catenated += line[:-1]
@ -234,10 +253,10 @@ def concat_multi_lines(f):
yield firstlineno, catenated + line
lastline = None
firstlineno = None
catenated = ''
catenated = ""
if lastline is not None:
print_err(lineno, line, 'Trailing backslash at the end of the file')
print_err(lineno, line, "Trailing backslash at the end of the file")
def get_known_directive_names():
@ -253,12 +272,12 @@ def get_known_directive_names():
"tools/compiletest/src/directive-list.rs",
),
"r",
encoding="utf8"
encoding="utf8",
) as fd:
content = fd.read()
return [
line.strip().replace('",', '').replace('"', '')
for line in content.split('\n')
line.strip().replace('",', "").replace('"', "")
for line in content.split("\n")
if filter_line(line)
]
@ -269,35 +288,42 @@ def get_known_directive_names():
# See <https://github.com/rust-lang/rust/issues/125813#issuecomment-2141953780>.
KNOWN_DIRECTIVE_NAMES = get_known_directive_names()
LINE_PATTERN = re.compile(r'''
LINE_PATTERN = re.compile(
r"""
//@\s+
(?P<negated>!?)(?P<cmd>[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)
(?P<args>.*)$
''', re.X | re.UNICODE)
""",
re.X | re.UNICODE,
)
def get_commands(template):
with io.open(template, encoding='utf-8') as f:
with io.open(template, encoding="utf-8") as f:
for lineno, line in concat_multi_lines(f):
m = LINE_PATTERN.search(line)
if not m:
continue
cmd = m.group('cmd')
negated = (m.group('negated') == '!')
cmd = m.group("cmd")
negated = m.group("negated") == "!"
if not negated and cmd in KNOWN_DIRECTIVE_NAMES:
continue
args = m.group('args')
args = m.group("args")
if args and not args[:1].isspace():
print_err(lineno, line, 'Invalid template syntax')
print_err(lineno, line, "Invalid template syntax")
continue
try:
args = shlex.split(args)
except UnicodeEncodeError:
args = [arg.decode('utf-8') for arg in shlex.split(args.encode('utf-8'))]
args = [
arg.decode("utf-8") for arg in shlex.split(args.encode("utf-8"))
]
except Exception as exc:
raise Exception("line {}: {}".format(lineno + 1, exc)) from None
yield Command(negated=negated, cmd=cmd, args=args, lineno=lineno+1, context=line)
yield Command(
negated=negated, cmd=cmd, args=args, lineno=lineno + 1, context=line
)
def _flatten(node, acc):
@ -312,22 +338,24 @@ def _flatten(node, acc):
def flatten(node):
acc = []
_flatten(node, acc)
return ''.join(acc)
return "".join(acc)
def make_xml(text):
xml = ET.XML('<xml>%s</xml>' % text)
xml = ET.XML("<xml>%s</xml>" % text)
return xml
def normalize_xpath(path):
path = path.replace("{{channel}}", channel)
if path.startswith('//'):
return '.' + path # avoid warnings
elif path.startswith('.//'):
if path.startswith("//"):
return "." + path # avoid warnings
elif path.startswith(".//"):
return path
else:
raise InvalidCheck('Non-absolute XPath is not supported due to implementation issues')
raise InvalidCheck(
"Non-absolute XPath is not supported due to implementation issues"
)
class CachedFiles(object):
@ -338,12 +366,12 @@ class CachedFiles(object):
self.last_path = None
def resolve_path(self, path):
if path != '-':
if path != "-":
path = os.path.normpath(path)
self.last_path = path
return path
elif self.last_path is None:
raise InvalidCheck('Tried to use the previous path in the first command')
raise InvalidCheck("Tried to use the previous path in the first command")
else:
return self.last_path
@ -356,10 +384,10 @@ class CachedFiles(object):
return self.files[path]
abspath = self.get_absolute_path(path)
if not(os.path.exists(abspath) and os.path.isfile(abspath)):
raise FailedCheck('File does not exist {!r}'.format(path))
if not (os.path.exists(abspath) and os.path.isfile(abspath)):
raise FailedCheck("File does not exist {!r}".format(path))
with io.open(abspath, encoding='utf-8') as f:
with io.open(abspath, encoding="utf-8") as f:
data = f.read()
self.files[path] = data
return data
@ -370,15 +398,15 @@ class CachedFiles(object):
return self.trees[path]
abspath = self.get_absolute_path(path)
if not(os.path.exists(abspath) and os.path.isfile(abspath)):
raise FailedCheck('File does not exist {!r}'.format(path))
if not (os.path.exists(abspath) and os.path.isfile(abspath)):
raise FailedCheck("File does not exist {!r}".format(path))
with io.open(abspath, encoding='utf-8') as f:
with io.open(abspath, encoding="utf-8") as f:
try:
tree = ET.fromstringlist(f.readlines(), CustomHTMLParser())
except Exception as e:
raise RuntimeError( # noqa: B904 FIXME: py2
'Cannot parse an HTML file {!r}: {}'.format(path, e)
raise RuntimeError( # noqa: B904 FIXME: py2
"Cannot parse an HTML file {!r}: {}".format(path, e)
)
self.trees[path] = tree
return self.trees[path]
@ -386,8 +414,8 @@ class CachedFiles(object):
def get_dir(self, path):
path = self.resolve_path(path)
abspath = self.get_absolute_path(path)
if not(os.path.exists(abspath) and os.path.isdir(abspath)):
raise FailedCheck('Directory does not exist {!r}'.format(path))
if not (os.path.exists(abspath) and os.path.isdir(abspath)):
raise FailedCheck("Directory does not exist {!r}".format(path))
def check_string(data, pat, regexp):
@ -397,8 +425,8 @@ def check_string(data, pat, regexp):
elif regexp:
return re.search(pat, data, flags=re.UNICODE) is not None
else:
data = ' '.join(data.split())
pat = ' '.join(pat.split())
data = " ".join(data.split())
pat = " ".join(pat.split())
return pat in data
@ -444,19 +472,19 @@ def get_tree_count(tree, path):
def check_snapshot(snapshot_name, actual_tree, normalize_to_text):
assert rust_test_path.endswith('.rs')
snapshot_path = '{}.{}.{}'.format(rust_test_path[:-3], snapshot_name, 'html')
assert rust_test_path.endswith(".rs")
snapshot_path = "{}.{}.{}".format(rust_test_path[:-3], snapshot_name, "html")
try:
with open(snapshot_path, 'r') as snapshot_file:
with open(snapshot_path, "r") as snapshot_file:
expected_str = snapshot_file.read().replace("{{channel}}", channel)
except FileNotFoundError:
if bless:
expected_str = None
else:
raise FailedCheck('No saved snapshot value') # noqa: B904 FIXME: py2
raise FailedCheck("No saved snapshot value") # noqa: B904 FIXME: py2
if not normalize_to_text:
actual_str = ET.tostring(actual_tree).decode('utf-8')
actual_str = ET.tostring(actual_tree).decode("utf-8")
else:
actual_str = flatten(actual_tree)
@ -464,64 +492,66 @@ def check_snapshot(snapshot_name, actual_tree, normalize_to_text):
# 1. Is --bless
# 2. Are actual and expected tree different
# 3. Are actual and expected text different
if not expected_str \
or (not normalize_to_text and \
not compare_tree(make_xml(actual_str), make_xml(expected_str), stderr)) \
or (normalize_to_text and actual_str != expected_str):
if (
not expected_str
or (
not normalize_to_text
and not compare_tree(make_xml(actual_str), make_xml(expected_str), stderr)
)
or (normalize_to_text and actual_str != expected_str)
):
if bless:
with open(snapshot_path, 'w') as snapshot_file:
with open(snapshot_path, "w") as snapshot_file:
actual_str = actual_str.replace(channel, "{{channel}}")
snapshot_file.write(actual_str)
else:
print('--- expected ---\n')
print("--- expected ---\n")
print(expected_str)
print('\n\n--- actual ---\n')
print("\n\n--- actual ---\n")
print(actual_str)
print()
raise FailedCheck('Actual snapshot value is different than expected')
raise FailedCheck("Actual snapshot value is different than expected")
# Adapted from https://github.com/formencode/formencode/blob/3a1ba9de2fdd494dd945510a4568a3afeddb0b2e/formencode/doctest_xml_compare.py#L72-L120
def compare_tree(x1, x2, reporter=None):
if x1.tag != x2.tag:
if reporter:
reporter('Tags do not match: %s and %s' % (x1.tag, x2.tag))
reporter("Tags do not match: %s and %s" % (x1.tag, x2.tag))
return False
for name, value in x1.attrib.items():
if x2.attrib.get(name) != value:
if reporter:
reporter('Attributes do not match: %s=%r, %s=%r'
% (name, value, name, x2.attrib.get(name)))
reporter(
"Attributes do not match: %s=%r, %s=%r"
% (name, value, name, x2.attrib.get(name))
)
return False
for name in x2.attrib:
if name not in x1.attrib:
if reporter:
reporter('x2 has an attribute x1 is missing: %s'
% name)
reporter("x2 has an attribute x1 is missing: %s" % name)
return False
if not text_compare(x1.text, x2.text):
if reporter:
reporter('text: %r != %r' % (x1.text, x2.text))
reporter("text: %r != %r" % (x1.text, x2.text))
return False
if not text_compare(x1.tail, x2.tail):
if reporter:
reporter('tail: %r != %r' % (x1.tail, x2.tail))
reporter("tail: %r != %r" % (x1.tail, x2.tail))
return False
cl1 = list(x1)
cl2 = list(x2)
if len(cl1) != len(cl2):
if reporter:
reporter('children length differs, %i != %i'
% (len(cl1), len(cl2)))
reporter("children length differs, %i != %i" % (len(cl1), len(cl2)))
return False
i = 0
for c1, c2 in zip(cl1, cl2):
i += 1
if not compare_tree(c1, c2, reporter=reporter):
if reporter:
reporter('children %i do not match: %s'
% (i, c1.tag))
reporter("children %i do not match: %s" % (i, c1.tag))
return False
return True
@ -529,14 +559,14 @@ def compare_tree(x1, x2, reporter=None):
def text_compare(t1, t2):
if not t1 and not t2:
return True
if t1 == '*' or t2 == '*':
if t1 == "*" or t2 == "*":
return True
return (t1 or '').strip() == (t2 or '').strip()
return (t1 or "").strip() == (t2 or "").strip()
def stderr(*args):
if sys.version_info.major < 3:
file = codecs.getwriter('utf-8')(sys.stderr)
file = codecs.getwriter("utf-8")(sys.stderr)
else:
file = sys.stderr
@ -556,21 +586,25 @@ def print_err(lineno, context, err, message=None):
def get_nb_matching_elements(cache, c, regexp, stop_at_first):
tree = cache.get_tree(c.args[0])
pat, sep, attr = c.args[1].partition('/@')
pat, sep, attr = c.args[1].partition("/@")
if sep: # attribute
tree = cache.get_tree(c.args[0])
return check_tree_attr(tree, pat, attr, c.args[2], False)
else: # normalized text
pat = c.args[1]
if pat.endswith('/text()'):
if pat.endswith("/text()"):
pat = pat[:-7]
return check_tree_text(cache.get_tree(c.args[0]), pat, c.args[2], regexp, stop_at_first)
return check_tree_text(
cache.get_tree(c.args[0]), pat, c.args[2], regexp, stop_at_first
)
def check_files_in_folder(c, cache, folder, files):
files = files.strip()
if not files.startswith('[') or not files.endswith(']'):
raise InvalidCheck("Expected list as second argument of {} (ie '[]')".format(c.cmd))
if not files.startswith("[") or not files.endswith("]"):
raise InvalidCheck(
"Expected list as second argument of {} (ie '[]')".format(c.cmd)
)
folder = cache.get_absolute_path(folder)
@ -592,12 +626,18 @@ def check_files_in_folder(c, cache, folder, files):
error = 0
if len(files_set) != 0:
print_err(c.lineno, c.context, "Entries not found in folder `{}`: `{}`".format(
folder, files_set))
print_err(
c.lineno,
c.context,
"Entries not found in folder `{}`: `{}`".format(folder, files_set),
)
error += 1
if len(folder_set) != 0:
print_err(c.lineno, c.context, "Extra entries in folder `{}`: `{}`".format(
folder, folder_set))
print_err(
c.lineno,
c.context,
"Extra entries in folder `{}`: `{}`".format(folder, folder_set),
)
error += 1
return error == 0
@ -608,11 +648,11 @@ ERR_COUNT = 0
def check_command(c, cache):
try:
cerr = ""
if c.cmd in ['has', 'hasraw', 'matches', 'matchesraw']: # string test
regexp = c.cmd.startswith('matches')
if c.cmd in ["has", "hasraw", "matches", "matchesraw"]: # string test
regexp = c.cmd.startswith("matches")
# has <path> = file existence
if len(c.args) == 1 and not regexp and 'raw' not in c.cmd:
if len(c.args) == 1 and not regexp and "raw" not in c.cmd:
try:
cache.get_file(c.args[0])
ret = True
@ -620,24 +660,24 @@ def check_command(c, cache):
cerr = str(err)
ret = False
# hasraw/matchesraw <path> <pat> = string test
elif len(c.args) == 2 and 'raw' in c.cmd:
elif len(c.args) == 2 and "raw" in c.cmd:
cerr = "`PATTERN` did not match"
ret = check_string(cache.get_file(c.args[0]), c.args[1], regexp)
# has/matches <path> <pat> <match> = XML tree test
elif len(c.args) == 3 and 'raw' not in c.cmd:
elif len(c.args) == 3 and "raw" not in c.cmd:
cerr = "`XPATH PATTERN` did not match"
ret = get_nb_matching_elements(cache, c, regexp, True) != 0
else:
raise InvalidCheck('Invalid number of {} arguments'.format(c.cmd))
raise InvalidCheck("Invalid number of {} arguments".format(c.cmd))
elif c.cmd == 'files': # check files in given folder
if len(c.args) != 2: # files <folder path> <file list>
elif c.cmd == "files": # check files in given folder
if len(c.args) != 2: # files <folder path> <file list>
raise InvalidCheck("Invalid number of {} arguments".format(c.cmd))
elif c.negated:
raise InvalidCheck("{} doesn't support negative check".format(c.cmd))
ret = check_files_in_folder(c, cache, c.args[0], c.args[1])
elif c.cmd == 'count': # count test
elif c.cmd == "count": # count test
if len(c.args) == 3: # count <path> <pat> <count> = count test
expected = int(c.args[2])
found = get_tree_count(cache.get_tree(c.args[0]), c.args[1])
@ -649,15 +689,15 @@ def check_command(c, cache):
cerr = "Expected {} occurrences but found {}".format(expected, found)
ret = found == expected
else:
raise InvalidCheck('Invalid number of {} arguments'.format(c.cmd))
raise InvalidCheck("Invalid number of {} arguments".format(c.cmd))
elif c.cmd == 'snapshot': # snapshot test
elif c.cmd == "snapshot": # snapshot test
if len(c.args) == 3: # snapshot <snapshot-name> <html-path> <xpath>
[snapshot_name, html_path, pattern] = c.args
tree = cache.get_tree(html_path)
xpath = normalize_xpath(pattern)
normalize_to_text = False
if xpath.endswith('/text()'):
if xpath.endswith("/text()"):
xpath = xpath[:-7]
normalize_to_text = True
@ -671,13 +711,15 @@ def check_command(c, cache):
cerr = str(err)
ret = False
elif len(subtrees) == 0:
raise FailedCheck('XPATH did not match')
raise FailedCheck("XPATH did not match")
else:
raise FailedCheck('Expected 1 match, but found {}'.format(len(subtrees)))
raise FailedCheck(
"Expected 1 match, but found {}".format(len(subtrees))
)
else:
raise InvalidCheck('Invalid number of {} arguments'.format(c.cmd))
raise InvalidCheck("Invalid number of {} arguments".format(c.cmd))
elif c.cmd == 'has-dir': # has-dir test
elif c.cmd == "has-dir": # has-dir test
if len(c.args) == 1: # has-dir <path> = has-dir test
try:
cache.get_dir(c.args[0])
@ -686,22 +728,22 @@ def check_command(c, cache):
cerr = str(err)
ret = False
else:
raise InvalidCheck('Invalid number of {} arguments'.format(c.cmd))
raise InvalidCheck("Invalid number of {} arguments".format(c.cmd))
elif c.cmd == 'valid-html':
raise InvalidCheck('Unimplemented valid-html')
elif c.cmd == "valid-html":
raise InvalidCheck("Unimplemented valid-html")
elif c.cmd == 'valid-links':
raise InvalidCheck('Unimplemented valid-links')
elif c.cmd == "valid-links":
raise InvalidCheck("Unimplemented valid-links")
else:
raise InvalidCheck('Unrecognized {}'.format(c.cmd))
raise InvalidCheck("Unrecognized {}".format(c.cmd))
if ret == c.negated:
raise FailedCheck(cerr)
except FailedCheck as err:
message = '{}{} check failed'.format('!' if c.negated else '', c.cmd)
message = "{}{} check failed".format("!" if c.negated else "", c.cmd)
print_err(c.lineno, c.context, str(err), message)
except InvalidCheck as err:
print_err(c.lineno, c.context, str(err))
@ -713,18 +755,18 @@ def check(target, commands):
check_command(c, cache)
if __name__ == '__main__':
if __name__ == "__main__":
if len(sys.argv) not in [3, 4]:
stderr('Usage: {} <doc dir> <template> [--bless]'.format(sys.argv[0]))
stderr("Usage: {} <doc dir> <template> [--bless]".format(sys.argv[0]))
raise SystemExit(1)
rust_test_path = sys.argv[2]
if len(sys.argv) > 3 and sys.argv[3] == '--bless':
if len(sys.argv) > 3 and sys.argv[3] == "--bless":
bless = True
else:
# We only support `--bless` at the end of the arguments.
# This assert is to prevent silent failures.
assert '--bless' not in sys.argv
assert "--bless" not in sys.argv
bless = False
check(sys.argv[1], get_commands(rust_test_path))
if ERR_COUNT:

View file

@ -45,7 +45,7 @@ def normalize_whitespace(s):
def breakpoint_callback(frame, bp_loc, dict):
"""This callback is registered with every breakpoint and makes sure that the
frame containing the breakpoint location is selected """
frame containing the breakpoint location is selected"""
# HACK(eddyb) print a newline to avoid continuing an unfinished line.
print("")
@ -79,7 +79,7 @@ def execute_command(command_interpreter, command):
if res.Succeeded():
if res.HasResult():
print(normalize_whitespace(res.GetOutput() or ''), end='\n')
print(normalize_whitespace(res.GetOutput() or ""), end="\n")
# If the command introduced any breakpoints, make sure to register
# them with the breakpoint
@ -89,20 +89,32 @@ def execute_command(command_interpreter, command):
breakpoint_id = new_breakpoints.pop()
if breakpoint_id in registered_breakpoints:
print_debug("breakpoint with id %s is already registered. Ignoring." %
str(breakpoint_id))
print_debug(
"breakpoint with id %s is already registered. Ignoring."
% str(breakpoint_id)
)
else:
print_debug("registering breakpoint callback, id = " + str(breakpoint_id))
callback_command = ("breakpoint command add -F breakpoint_callback " +
str(breakpoint_id))
print_debug(
"registering breakpoint callback, id = " + str(breakpoint_id)
)
callback_command = (
"breakpoint command add -F breakpoint_callback "
+ str(breakpoint_id)
)
command_interpreter.HandleCommand(callback_command, res)
if res.Succeeded():
print_debug("successfully registered breakpoint callback, id = " +
str(breakpoint_id))
print_debug(
"successfully registered breakpoint callback, id = "
+ str(breakpoint_id)
)
registered_breakpoints.add(breakpoint_id)
else:
print("Error while trying to register breakpoint callback, id = " +
str(breakpoint_id) + ", message = " + str(res.GetError()))
print(
"Error while trying to register breakpoint callback, id = "
+ str(breakpoint_id)
+ ", message = "
+ str(res.GetError())
)
else:
print(res.GetError())
@ -117,14 +129,16 @@ def start_breakpoint_listener(target):
try:
while True:
if listener.WaitForEvent(120, event):
if lldb.SBBreakpoint.EventIsBreakpointEvent(event) and \
lldb.SBBreakpoint.GetBreakpointEventTypeFromEvent(event) == \
lldb.eBreakpointEventTypeAdded:
if (
lldb.SBBreakpoint.EventIsBreakpointEvent(event)
and lldb.SBBreakpoint.GetBreakpointEventTypeFromEvent(event)
== lldb.eBreakpointEventTypeAdded
):
global new_breakpoints
breakpoint = lldb.SBBreakpoint.GetBreakpointFromEvent(event)
print_debug("breakpoint added, id = " + str(breakpoint.id))
new_breakpoints.append(breakpoint.id)
except BaseException: # explicitly catch ctrl+c/sysexit
except BaseException: # explicitly catch ctrl+c/sysexit
print_debug("breakpoint listener shutting down")
# Start the listener and let it run as a daemon
@ -133,7 +147,9 @@ def start_breakpoint_listener(target):
listener_thread.start()
# Register the listener with the target
target.GetBroadcaster().AddListener(listener, lldb.SBTarget.eBroadcastBitBreakpointChanged)
target.GetBroadcaster().AddListener(
listener, lldb.SBTarget.eBroadcastBitBreakpointChanged
)
def start_watchdog():
@ -159,6 +175,7 @@ def start_watchdog():
watchdog_thread.daemon = True
watchdog_thread.start()
####################################################################################################
# ~main
####################################################################################################
@ -193,8 +210,14 @@ target_error = lldb.SBError()
target = debugger.CreateTarget(target_path, None, None, True, target_error)
if not target:
print("Could not create debugging target '" + target_path + "': " +
str(target_error) + ". Aborting.", file=sys.stderr)
print(
"Could not create debugging target '"
+ target_path
+ "': "
+ str(target_error)
+ ". Aborting.",
file=sys.stderr,
)
sys.exit(1)
@ -204,15 +227,19 @@ start_breakpoint_listener(target)
command_interpreter = debugger.GetCommandInterpreter()
try:
script_file = open(script_path, 'r')
script_file = open(script_path, "r")
for line in script_file:
command = line.strip()
if command == "run" or command == "r" or re.match("^process\s+launch.*", command):
if (
command == "run"
or command == "r"
or re.match("^process\s+launch.*", command)
):
# Before starting to run the program, let the thread sleep a bit, so all
# breakpoint added events can be processed
time.sleep(0.5)
if command != '':
if command != "":
execute_command(command_interpreter, command)
except IOError as e:

View file

@ -1,4 +1,25 @@
type synthetic add -l lldb_lookup.synthetic_lookup -x ".*" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)String$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^&(mut )?str$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^&(mut )?\\[.+\\]$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(std::ffi::([a-z_]+::)+)OsString$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)Vec<.+>$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)VecDeque<.+>$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)BTreeSet<.+>$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)BTreeMap<.+>$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(std::collections::([a-z_]+::)+)HashMap<.+>$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(std::collections::([a-z_]+::)+)HashSet<.+>$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)Rc<.+>$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(alloc::([a-z_]+::)+)Arc<.+>$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)Cell<.+>$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)Ref<.+>$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)RefMut<.+>$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)RefCell<.+>$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(core::([a-z_]+::)+)NonZero<.+>$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^core::num::([a-z_]+::)*NonZero.+$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(std::([a-z_]+::)+)PathBuf$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^&(mut )?(std::([a-z_]+::)+)Path$" --category Rust
type synthetic add -l lldb_lookup.synthetic_lookup -x "^(.*)$" --category Rust
type summary add -F _ -e -x -h "^.*$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)String$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^&(mut )?str$" --category Rust
type summary add -F lldb_lookup.summary_lookup -e -x -h "^&(mut )?\\[.+\\]$" --category Rust

View file

@ -1,7 +1,12 @@
import sys
from lldb import SBData, SBError, eBasicTypeLong, eBasicTypeUnsignedLong, \
eBasicTypeUnsignedChar
from lldb import (
SBData,
SBError,
eBasicTypeLong,
eBasicTypeUnsignedLong,
eBasicTypeUnsignedChar,
)
# from lldb.formatters import Logger
@ -50,13 +55,17 @@ class ValueBuilder:
def from_int(self, name, value):
# type: (str, int) -> SBValue
type = self.valobj.GetType().GetBasicType(eBasicTypeLong)
data = SBData.CreateDataFromSInt64Array(self.endianness, self.pointer_size, [value])
data = SBData.CreateDataFromSInt64Array(
self.endianness, self.pointer_size, [value]
)
return self.valobj.CreateValueFromData(name, data, type)
def from_uint(self, name, value):
# type: (str, int) -> SBValue
type = self.valobj.GetType().GetBasicType(eBasicTypeUnsignedLong)
data = SBData.CreateDataFromUInt64Array(self.endianness, self.pointer_size, [value])
data = SBData.CreateDataFromUInt64Array(
self.endianness, self.pointer_size, [value]
)
return self.valobj.CreateValueFromData(name, data, type)
@ -127,13 +136,17 @@ class EmptySyntheticProvider:
def SizeSummaryProvider(valobj, dict):
# type: (SBValue, dict) -> str
return 'size=' + str(valobj.GetNumChildren())
return "size=" + str(valobj.GetNumChildren())
def vec_to_string(vec):
length = vec.GetNumChildren()
chars = [vec.GetChildAtIndex(i).GetValueAsUnsigned() for i in range(length)]
return bytes(chars).decode(errors='replace') if PY3 else "".join(chr(char) for char in chars)
return (
bytes(chars).decode(errors="replace")
if PY3
else "".join(chr(char) for char in chars)
)
def StdStringSummaryProvider(valobj, dict):
@ -172,7 +185,7 @@ def StdStrSummaryProvider(valobj, dict):
error = SBError()
process = data_ptr.GetProcess()
data = process.ReadMemory(start, length, error)
data = data.decode(encoding='UTF-8') if PY3 else data
data = data.decode(encoding="UTF-8") if PY3 else data
return '"%s"' % data
@ -199,9 +212,9 @@ def StdPathSummaryProvider(valobj, dict):
data = process.ReadMemory(start, length, error)
if PY3:
try:
data = data.decode(encoding='UTF-8')
data = data.decode(encoding="UTF-8")
except UnicodeDecodeError:
return '%r' % data
return "%r" % data
return '"%s"' % data
@ -250,8 +263,10 @@ class StructSyntheticProvider:
# type: () -> bool
return True
class ClangEncodedEnumProvider:
"""Pretty-printer for 'clang-encoded' enums support implemented in LLDB"""
DISCRIMINANT_MEMBER_NAME = "$discr$"
VALUE_MEMBER_NAME = "value"
@ -260,7 +275,7 @@ class ClangEncodedEnumProvider:
self.update()
def has_children(self):
return True
return True
def num_children(self):
if self.is_default:
@ -276,25 +291,32 @@ class ClangEncodedEnumProvider:
def get_child_at_index(self, index):
if index == 0:
return self.variant.GetChildMemberWithName(ClangEncodedEnumProvider.VALUE_MEMBER_NAME)
return self.variant.GetChildMemberWithName(
ClangEncodedEnumProvider.VALUE_MEMBER_NAME
)
if index == 1:
return self.variant.GetChildMemberWithName(
ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME)
ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME
)
def update(self):
all_variants = self.valobj.GetChildAtIndex(0)
index = self._getCurrentVariantIndex(all_variants)
self.variant = all_variants.GetChildAtIndex(index)
self.is_default = self.variant.GetIndexOfChildWithName(
ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME) == -1
self.is_default = (
self.variant.GetIndexOfChildWithName(
ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME
)
== -1
)
def _getCurrentVariantIndex(self, all_variants):
default_index = 0
for i in range(all_variants.GetNumChildren()):
variant = all_variants.GetChildAtIndex(i)
discr = variant.GetChildMemberWithName(
ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME)
ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME
)
if discr.IsValid():
discr_unsigned_value = discr.GetValueAsUnsigned()
if variant.GetName() == f"$variant${discr_unsigned_value}":
@ -303,6 +325,7 @@ class ClangEncodedEnumProvider:
default_index = i
return default_index
class TupleSyntheticProvider:
"""Pretty-printer for tuples and tuple enum variants"""
@ -336,7 +359,9 @@ class TupleSyntheticProvider:
else:
field = self.type.GetFieldAtIndex(index)
element = self.valobj.GetChildMemberWithName(field.name)
return self.valobj.CreateValueFromData(str(index), element.GetData(), element.GetType())
return self.valobj.CreateValueFromData(
str(index), element.GetData(), element.GetType()
)
def update(self):
# type: () -> None
@ -373,7 +398,7 @@ class StdVecSyntheticProvider:
def get_child_index(self, name):
# type: (str) -> int
index = name.lstrip('[').rstrip(']')
index = name.lstrip("[").rstrip("]")
if index.isdigit():
return int(index)
else:
@ -383,15 +408,21 @@ class StdVecSyntheticProvider:
# type: (int) -> SBValue
start = self.data_ptr.GetValueAsUnsigned()
address = start + index * self.element_type_size
element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.element_type)
element = self.data_ptr.CreateValueFromAddress(
"[%s]" % index, address, self.element_type
)
return element
def update(self):
# type: () -> None
self.length = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned()
self.buf = self.valobj.GetChildMemberWithName("buf").GetChildMemberWithName("inner")
self.buf = self.valobj.GetChildMemberWithName("buf").GetChildMemberWithName(
"inner"
)
self.data_ptr = unwrap_unique_or_non_null(self.buf.GetChildMemberWithName("ptr"))
self.data_ptr = unwrap_unique_or_non_null(
self.buf.GetChildMemberWithName("ptr")
)
self.element_type = self.valobj.GetType().GetTemplateArgumentType(0)
self.element_type_size = self.element_type.GetByteSize()
@ -412,7 +443,7 @@ class StdSliceSyntheticProvider:
def get_child_index(self, name):
# type: (str) -> int
index = name.lstrip('[').rstrip(']')
index = name.lstrip("[").rstrip("]")
if index.isdigit():
return int(index)
else:
@ -422,7 +453,9 @@ class StdSliceSyntheticProvider:
# type: (int) -> SBValue
start = self.data_ptr.GetValueAsUnsigned()
address = start + index * self.element_type_size
element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.element_type)
element = self.data_ptr.CreateValueFromAddress(
"[%s]" % index, address, self.element_type
)
return element
def update(self):
@ -457,7 +490,7 @@ class StdVecDequeSyntheticProvider:
def get_child_index(self, name):
# type: (str) -> int
index = name.lstrip('[').rstrip(']')
index = name.lstrip("[").rstrip("]")
if index.isdigit() and int(index) < self.size:
return int(index)
else:
@ -467,20 +500,26 @@ class StdVecDequeSyntheticProvider:
# type: (int) -> SBValue
start = self.data_ptr.GetValueAsUnsigned()
address = start + ((index + self.head) % self.cap) * self.element_type_size
element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.element_type)
element = self.data_ptr.CreateValueFromAddress(
"[%s]" % index, address, self.element_type
)
return element
def update(self):
# type: () -> None
self.head = self.valobj.GetChildMemberWithName("head").GetValueAsUnsigned()
self.size = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned()
self.buf = self.valobj.GetChildMemberWithName("buf").GetChildMemberWithName("inner")
self.buf = self.valobj.GetChildMemberWithName("buf").GetChildMemberWithName(
"inner"
)
cap = self.buf.GetChildMemberWithName("cap")
if cap.GetType().num_fields == 1:
cap = cap.GetChildAtIndex(0)
self.cap = cap.GetValueAsUnsigned()
self.data_ptr = unwrap_unique_or_non_null(self.buf.GetChildMemberWithName("ptr"))
self.data_ptr = unwrap_unique_or_non_null(
self.buf.GetChildMemberWithName("ptr")
)
self.element_type = self.valobj.GetType().GetTemplateArgumentType(0)
self.element_type_size = self.element_type.GetByteSize()
@ -510,7 +549,7 @@ class StdOldHashMapSyntheticProvider:
def get_child_index(self, name):
# type: (str) -> int
index = name.lstrip('[').rstrip(']')
index = name.lstrip("[").rstrip("]")
if index.isdigit():
return int(index)
else:
@ -525,8 +564,14 @@ class StdOldHashMapSyntheticProvider:
hashes = self.hash_uint_size * self.capacity
align = self.pair_type_size
# See `libcore/alloc.rs:padding_needed_for`
len_rounded_up = (((((hashes + align) % self.modulo - 1) % self.modulo) & ~(
(align - 1) % self.modulo)) % self.modulo - hashes) % self.modulo
len_rounded_up = (
(
(((hashes + align) % self.modulo - 1) % self.modulo)
& ~((align - 1) % self.modulo)
)
% self.modulo
- hashes
) % self.modulo
# len_rounded_up = ((hashes + align - 1) & ~(align - 1)) - hashes
pairs_offset = hashes + len_rounded_up
@ -535,12 +580,16 @@ class StdOldHashMapSyntheticProvider:
table_index = self.valid_indices[index]
idx = table_index & self.capacity_mask
address = pairs_start + idx * self.pair_type_size
element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.pair_type)
element = self.data_ptr.CreateValueFromAddress(
"[%s]" % index, address, self.pair_type
)
if self.show_values:
return element
else:
key = element.GetChildAtIndex(0)
return self.valobj.CreateValueFromData("[%s]" % index, key.GetData(), key.GetType())
return self.valobj.CreateValueFromData(
"[%s]" % index, key.GetData(), key.GetType()
)
def update(self):
# type: () -> None
@ -551,10 +600,12 @@ class StdOldHashMapSyntheticProvider:
self.hashes = self.table.GetChildMemberWithName("hashes")
self.hash_uint_type = self.hashes.GetType()
self.hash_uint_size = self.hashes.GetType().GetByteSize()
self.modulo = 2 ** self.hash_uint_size
self.modulo = 2**self.hash_uint_size
self.data_ptr = self.hashes.GetChildAtIndex(0).GetChildAtIndex(0)
self.capacity_mask = self.table.GetChildMemberWithName("capacity_mask").GetValueAsUnsigned()
self.capacity_mask = self.table.GetChildMemberWithName(
"capacity_mask"
).GetValueAsUnsigned()
self.capacity = (self.capacity_mask + 1) % self.modulo
marker = self.table.GetChildMemberWithName("marker").GetType() # type: SBType
@ -564,8 +615,9 @@ class StdOldHashMapSyntheticProvider:
self.valid_indices = []
for idx in range(self.capacity):
address = self.data_ptr.GetValueAsUnsigned() + idx * self.hash_uint_size
hash_uint = self.data_ptr.CreateValueFromAddress("[%s]" % idx, address,
self.hash_uint_type)
hash_uint = self.data_ptr.CreateValueFromAddress(
"[%s]" % idx, address, self.hash_uint_type
)
hash_ptr = hash_uint.GetChildAtIndex(0).GetChildAtIndex(0)
if hash_ptr.GetValueAsUnsigned() != 0:
self.valid_indices.append(idx)
@ -592,7 +644,7 @@ class StdHashMapSyntheticProvider:
def get_child_index(self, name):
# type: (str) -> int
index = name.lstrip('[').rstrip(']')
index = name.lstrip("[").rstrip("]")
if index.isdigit():
return int(index)
else:
@ -605,19 +657,25 @@ class StdHashMapSyntheticProvider:
if self.new_layout:
idx = -(idx + 1)
address = pairs_start + idx * self.pair_type_size
element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.pair_type)
element = self.data_ptr.CreateValueFromAddress(
"[%s]" % index, address, self.pair_type
)
if self.show_values:
return element
else:
key = element.GetChildAtIndex(0)
return self.valobj.CreateValueFromData("[%s]" % index, key.GetData(), key.GetType())
return self.valobj.CreateValueFromData(
"[%s]" % index, key.GetData(), key.GetType()
)
def update(self):
# type: () -> None
table = self.table()
inner_table = table.GetChildMemberWithName("table")
capacity = inner_table.GetChildMemberWithName("bucket_mask").GetValueAsUnsigned() + 1
capacity = (
inner_table.GetChildMemberWithName("bucket_mask").GetValueAsUnsigned() + 1
)
ctrl = inner_table.GetChildMemberWithName("ctrl").GetChildAtIndex(0)
self.size = inner_table.GetChildMemberWithName("items").GetValueAsUnsigned()
@ -630,16 +688,21 @@ class StdHashMapSyntheticProvider:
if self.new_layout:
self.data_ptr = ctrl.Cast(self.pair_type.GetPointerType())
else:
self.data_ptr = inner_table.GetChildMemberWithName("data").GetChildAtIndex(0)
self.data_ptr = inner_table.GetChildMemberWithName("data").GetChildAtIndex(
0
)
u8_type = self.valobj.GetTarget().GetBasicType(eBasicTypeUnsignedChar)
u8_type_size = self.valobj.GetTarget().GetBasicType(eBasicTypeUnsignedChar).GetByteSize()
u8_type_size = (
self.valobj.GetTarget().GetBasicType(eBasicTypeUnsignedChar).GetByteSize()
)
self.valid_indices = []
for idx in range(capacity):
address = ctrl.GetValueAsUnsigned() + idx * u8_type_size
value = ctrl.CreateValueFromAddress("ctrl[%s]" % idx, address,
u8_type).GetValueAsUnsigned()
value = ctrl.CreateValueFromAddress(
"ctrl[%s]" % idx, address, u8_type
).GetValueAsUnsigned()
is_present = value & 128 == 0
if is_present:
self.valid_indices.append(idx)
@ -691,10 +754,16 @@ class StdRcSyntheticProvider:
self.value = self.ptr.GetChildMemberWithName("data" if is_atomic else "value")
self.strong = self.ptr.GetChildMemberWithName("strong").GetChildAtIndex(
0).GetChildMemberWithName("value")
self.weak = self.ptr.GetChildMemberWithName("weak").GetChildAtIndex(
0).GetChildMemberWithName("value")
self.strong = (
self.ptr.GetChildMemberWithName("strong")
.GetChildAtIndex(0)
.GetChildMemberWithName("value")
)
self.weak = (
self.ptr.GetChildMemberWithName("weak")
.GetChildAtIndex(0)
.GetChildMemberWithName("value")
)
self.value_builder = ValueBuilder(valobj)
@ -772,7 +841,9 @@ class StdCellSyntheticProvider:
def StdRefSummaryProvider(valobj, dict):
# type: (SBValue, dict) -> str
borrow = valobj.GetChildMemberWithName("borrow").GetValueAsSigned()
return "borrow={}".format(borrow) if borrow >= 0 else "borrow_mut={}".format(-borrow)
return (
"borrow={}".format(borrow) if borrow >= 0 else "borrow_mut={}".format(-borrow)
)
class StdRefSyntheticProvider:
@ -785,11 +856,16 @@ class StdRefSyntheticProvider:
borrow = valobj.GetChildMemberWithName("borrow")
value = valobj.GetChildMemberWithName("value")
if is_cell:
self.borrow = borrow.GetChildMemberWithName("value").GetChildMemberWithName("value")
self.borrow = borrow.GetChildMemberWithName("value").GetChildMemberWithName(
"value"
)
self.value = value.GetChildMemberWithName("value")
else:
self.borrow = borrow.GetChildMemberWithName("borrow").GetChildMemberWithName(
"value").GetChildMemberWithName("value")
self.borrow = (
borrow.GetChildMemberWithName("borrow")
.GetChildMemberWithName("value")
.GetChildMemberWithName("value")
)
self.value = value.Dereference()
self.value_builder = ValueBuilder(valobj)
@ -832,7 +908,7 @@ def StdNonZeroNumberSummaryProvider(valobj, _dict):
# FIXME: Avoid printing as character literal,
# see https://github.com/llvm/llvm-project/issues/65076.
if inner_inner.GetTypeName() in ['char', 'unsigned char']:
return str(inner_inner.GetValueAsSigned())
if inner_inner.GetTypeName() in ["char", "unsigned char"]:
return str(inner_inner.GetValueAsSigned())
else:
return inner_inner.GetValue()
return inner_inner.GetValue()

View file

@ -34,5 +34,8 @@
"rust-analyzer.rustc.source": "./Cargo.toml",
"rust-analyzer.cargo.extraEnv": {
"RUSTC_BOOTSTRAP": "1"
},
"rust-analyzer.server.extraEnv": {
"RUSTUP_TOOLCHAIN": "nightly"
}
}

View file

@ -54,7 +54,7 @@ STD_REF_MUT_REGEX = re.compile(r"^(core::([a-z_]+::)+)RefMut<.+>$")
STD_REF_CELL_REGEX = re.compile(r"^(core::([a-z_]+::)+)RefCell<.+>$")
STD_NONZERO_NUMBER_REGEX = re.compile(r"^(core::([a-z_]+::)+)NonZero<.+>$")
STD_PATHBUF_REGEX = re.compile(r"^(std::([a-z_]+::)+)PathBuf$")
STD_PATH_REGEX = re.compile(r"^&(mut )?(std::([a-z_]+::)+)Path$")
STD_PATH_REGEX = re.compile(r"^&(mut )?(std::([a-z_]+::)+)Path$")
TUPLE_ITEM_REGEX = re.compile(r"__\d+$")
@ -84,6 +84,7 @@ STD_TYPE_TO_REGEX = {
RustType.STD_PATH: STD_PATH_REGEX,
}
def is_tuple_fields(fields):
# type: (list) -> bool
return all(TUPLE_ITEM_REGEX.match(str(field.name)) for field in fields)

View file

@ -2,6 +2,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet, IndexEntry};
use rustc_hir as hir;
use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
use rustc_middle::bug;
use rustc_middle::ty::fold::fold_regions;
use rustc_middle::ty::{self, Region, Ty};
use rustc_span::def_id::DefId;
use rustc_span::symbol::{Symbol, kw};
@ -182,7 +183,7 @@ fn clean_param_env<'tcx>(
.is_some_and(|pred| tcx.lang_items().sized_trait() == Some(pred.def_id()))
})
.map(|pred| {
tcx.fold_regions(pred, |r, _| match *r {
fold_regions(tcx, pred, |r, _| match *r {
// FIXME: Don't `unwrap_or`, I think we should panic if we encounter an infer var that
// we can't map to a concrete region. However, `AutoTraitFinder` *does* leak those kinds
// of `ReVar`s for some reason at the time of writing. See `rustdoc-ui/` tests.

View file

@ -2647,7 +2647,7 @@ fn filter_doc_attr(normal: &mut ast::NormalAttr, is_inline: bool) {
});
args.tokens = TokenStream::new(tokens);
}
ast::AttrArgs::Empty | ast::AttrArgs::Eq(..) => {}
ast::AttrArgs::Empty | ast::AttrArgs::Eq { .. } => {}
}
}

View file

@ -1241,19 +1241,6 @@ impl Attributes {
}
}
impl PartialEq for Attributes {
fn eq(&self, rhs: &Self) -> bool {
self.doc_strings == rhs.doc_strings
&& self
.other_attrs
.iter()
.map(|attr| attr.id)
.eq(rhs.other_attrs.iter().map(|attr| attr.id))
}
}
impl Eq for Attributes {}
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub(crate) enum GenericBound {
TraitBound(PolyTrait, hir::TraitBoundModifiers),

View file

@ -5,12 +5,12 @@ use std::{io, mem};
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::unord::UnordSet;
use rustc_errors::TerminalUrl;
use rustc_errors::codes::*;
use rustc_errors::emitter::{
DynEmitter, HumanEmitter, HumanReadableErrorType, OutputTheme, stderr_destination,
};
use rustc_errors::json::JsonEmitter;
use rustc_errors::{ErrorGuaranteed, TerminalUrl};
use rustc_feature::UnstableFeatures;
use rustc_hir::def::Res;
use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId};
@ -326,7 +326,7 @@ pub(crate) fn run_global_ctxt(
show_coverage: bool,
render_options: RenderOptions,
output_format: OutputFormat,
) -> Result<(clean::Crate, RenderOptions, Cache), ErrorGuaranteed> {
) -> (clean::Crate, RenderOptions, Cache) {
// Certain queries assume that some checks were run elsewhere
// (see https://github.com/rust-lang/rust/pull/73566#issuecomment-656954425),
// so type-check everything other than function bodies in this crate before running lints.
@ -340,9 +340,7 @@ pub(crate) fn run_global_ctxt(
tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_type_wf(module))
});
if let Some(guar) = tcx.dcx().has_errors() {
return Err(guar);
}
tcx.dcx().abort_if_errors();
tcx.sess.time("missing_docs", || rustc_lint::check_crate(tcx));
tcx.sess.time("check_mod_attrs", || {
@ -446,11 +444,9 @@ pub(crate) fn run_global_ctxt(
LinkCollector { cx: &mut ctxt, visited_links: visited, ambiguous_links: ambiguous };
collector.resolve_ambiguities();
if let Some(guar) = tcx.dcx().has_errors() {
return Err(guar);
}
tcx.dcx().abort_if_errors();
Ok((krate, ctxt.render_options, ctxt.cache))
(krate, ctxt.render_options, ctxt.cache)
}
/// Due to <https://github.com/rust-lang/rust/pull/73566>,

View file

@ -16,7 +16,7 @@ pub(crate) use markdown::test as test_markdown;
use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
use rustc_errors::emitter::HumanReadableErrorType;
use rustc_errors::{ColorConfig, DiagCtxtHandle, ErrorGuaranteed, FatalError};
use rustc_errors::{ColorConfig, DiagCtxtHandle};
use rustc_hir::CRATE_HIR_ID;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_interface::interface;
@ -89,11 +89,7 @@ fn get_doctest_dir() -> io::Result<TempDir> {
TempFileBuilder::new().prefix("rustdoctest").tempdir()
}
pub(crate) fn run(
dcx: DiagCtxtHandle<'_>,
input: Input,
options: RustdocOptions,
) -> Result<(), ErrorGuaranteed> {
pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions) {
let invalid_codeblock_attributes_name = crate::lint::INVALID_CODEBLOCK_ATTRIBUTES.name;
// See core::create_config for what's going on here.
@ -167,7 +163,7 @@ pub(crate) fn run(
Err(error) => return crate::wrap_return(dcx, Err(error)),
};
let args_path = temp_dir.path().join("rustdoc-cfgs");
crate::wrap_return(dcx, generate_args_file(&args_path, &options))?;
crate::wrap_return(dcx, generate_args_file(&args_path, &options));
let CreateRunnableDocTests {
standalone_tests,
@ -179,7 +175,7 @@ pub(crate) fn run(
..
} = interface::run_compiler(config, |compiler| {
compiler.enter(|queries| {
let collector = queries.global_ctxt()?.enter(|tcx| {
let collector = queries.global_ctxt().enter(|tcx| {
let crate_name = tcx.crate_name(LOCAL_CRATE).to_string();
let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID);
let opts = scrape_test_config(crate_name, crate_attrs, args_path);
@ -196,13 +192,11 @@ pub(crate) fn run(
collector
});
if compiler.sess.dcx().has_errors().is_some() {
FatalError.raise();
}
compiler.sess.dcx().abort_if_errors();
Ok(collector)
collector
})
})?;
});
run_tests(opts, &rustdoc_options, &unused_extern_reports, standalone_tests, mergeable_tests);
@ -246,8 +240,6 @@ pub(crate) fn run(
eprintln!("{unused_extern_json}");
}
}
Ok(())
}
pub(crate) fn run_tests(

View file

@ -1,5 +1,5 @@
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_middle::ty::TyCtxt;
use tracing::debug;
use crate::clean;
use crate::config::RenderOptions;
@ -18,6 +18,19 @@ pub(crate) trait FormatRenderer<'tcx>: Sized {
/// This is true for html, and false for json. See #80664
const RUN_ON_MODULE: bool;
/// This associated type is the type where the current module information is stored.
///
/// For each module, we go through their items by calling for each item:
///
/// 1. `save_module_data`
/// 2. `item`
/// 3. `restore_module_data`
///
/// This is because the `item` method might update information in `self` (for example if the child
/// is a module). To prevent it from impacting the other children of the current module, we need to
/// reset the information between each call to `item` by using `restore_module_data`.
type ModuleData;
/// Sets up any state required for the renderer. When this is called the cache has already been
/// populated.
fn init(
@ -27,8 +40,20 @@ pub(crate) trait FormatRenderer<'tcx>: Sized {
tcx: TyCtxt<'tcx>,
) -> Result<(Self, clean::Crate), Error>;
/// Make a new renderer to render a child of the item currently being rendered.
fn make_child_renderer(&self) -> Self;
/// This method is called right before call [`Self::item`]. This method returns a type
/// containing information that needs to be reset after the [`Self::item`] method has been
/// called with the [`Self::restore_module_data`] method.
///
/// In short it goes like this:
///
/// ```ignore (not valid code)
/// let reset_data = renderer.save_module_data();
/// renderer.item(item)?;
/// renderer.restore_module_data(reset_data);
/// ```
fn save_module_data(&mut self) -> Self::ModuleData;
/// Used to reset current module's information.
fn restore_module_data(&mut self, info: Self::ModuleData);
/// Renders a single non-module item. This means no recursive sub-item rendering is required.
fn item(&mut self, item: clean::Item) -> Result<(), Error>;
@ -47,6 +72,40 @@ pub(crate) trait FormatRenderer<'tcx>: Sized {
fn cache(&self) -> &Cache;
}
fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>(
cx: &mut T,
item: clean::Item,
prof: &SelfProfilerRef,
) -> Result<(), Error> {
if item.is_mod() && T::RUN_ON_MODULE {
// modules are special because they add a namespace. We also need to
// recurse into the items of the module as well.
let _timer =
prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string());
cx.mod_item_in(&item)?;
let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) =
item.inner.kind
else {
unreachable!()
};
for it in module.items {
let info = cx.save_module_data();
run_format_inner(cx, it, prof)?;
cx.restore_module_data(info);
}
cx.mod_item_out()?;
// FIXME: checking `item.name.is_some()` is very implicit and leads to lots of special
// cases. Use an explicit match instead.
} else if let Some(item_name) = item.name
&& !item.is_extern_crate()
{
prof.generic_activity_with_arg("render_item", item_name.as_str()).run(|| cx.item(item))?;
}
Ok(())
}
/// Main method for rendering a crate.
pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>(
krate: clean::Crate,
@ -66,36 +125,8 @@ pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>(
}
// Render the crate documentation
let mut work = vec![(format_renderer.make_child_renderer(), krate.module)];
run_format_inner(&mut format_renderer, krate.module, prof)?;
while let Some((mut cx, item)) = work.pop() {
if item.is_mod() && T::RUN_ON_MODULE {
// modules are special because they add a namespace. We also need to
// recurse into the items of the module as well.
let _timer =
prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string());
cx.mod_item_in(&item)?;
let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) =
item.inner.kind
else {
unreachable!()
};
for it in module.items {
debug!("Adding {:?} to worklist", it.name);
work.push((cx.make_child_renderer(), it));
}
cx.mod_item_out()?;
// FIXME: checking `item.name.is_some()` is very implicit and leads to lots of special
// cases. Use an explicit match instead.
} else if let Some(item_name) = item.name
&& !item.is_extern_crate()
{
prof.generic_activity_with_arg("render_item", item_name.as_str())
.run(|| cx.item(item))?;
}
}
prof.verbose_generic_activity_with_arg("renderer_after_krate", T::descr())
.run(|| format_renderer.after_krate())
}

View file

@ -32,7 +32,8 @@ use std::iter::Peekable;
use std::ops::{ControlFlow, Range};
use std::path::PathBuf;
use std::str::{self, CharIndices};
use std::sync::OnceLock;
use std::sync::atomic::AtomicUsize;
use std::sync::{Arc, Weak};
use pulldown_cmark::{
BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag, TagEnd, html,
@ -1302,8 +1303,20 @@ impl LangString {
}
}
impl Markdown<'_> {
impl<'a> Markdown<'a> {
pub fn into_string(self) -> String {
// This is actually common enough to special-case
if self.content.is_empty() {
return String::new();
}
let mut s = String::with_capacity(self.content.len() * 3 / 2);
html::push_html(&mut s, self.into_iter());
s
}
fn into_iter(self) -> CodeBlocks<'a, 'a, impl Iterator<Item = Event<'a>>> {
let Markdown {
content: md,
links,
@ -1314,32 +1327,72 @@ impl Markdown<'_> {
heading_offset,
} = self;
// This is actually common enough to special-case
if md.is_empty() {
return String::new();
}
let mut replacer = |broken_link: BrokenLink<'_>| {
let replacer = move |broken_link: BrokenLink<'_>| {
links
.iter()
.find(|link| *link.original_text == *broken_link.reference)
.map(|link| (link.href.as_str().into(), link.tooltip.as_str().into()))
};
let p = Parser::new_with_broken_link_callback(md, main_body_opts(), Some(&mut replacer));
let p = Parser::new_with_broken_link_callback(md, main_body_opts(), Some(replacer));
let p = p.into_offset_iter();
let mut s = String::with_capacity(md.len() * 3 / 2);
ids.handle_footnotes(|ids, existing_footnotes| {
let p = HeadingLinks::new(p, None, ids, heading_offset);
let p = footnotes::Footnotes::new(p, existing_footnotes);
let p = LinkReplacer::new(p.map(|(ev, _)| ev), links);
let p = TableWrapper::new(p);
let p = CodeBlocks::new(p, codes, edition, playground);
html::push_html(&mut s, p);
});
CodeBlocks::new(p, codes, edition, playground)
})
}
s
/// Convert markdown to (summary, remaining) HTML.
///
/// - The summary is the first top-level Markdown element (usually a paragraph, but potentially
/// any block).
/// - The remaining docs contain everything after the summary.
pub(crate) fn split_summary_and_content(self) -> (Option<String>, Option<String>) {
if self.content.is_empty() {
return (None, None);
}
let mut p = self.into_iter();
let mut event_level = 0;
let mut summary_events = Vec::new();
let mut get_next_tag = false;
let mut end_of_summary = false;
while let Some(event) = p.next() {
match event {
Event::Start(_) => event_level += 1,
Event::End(kind) => {
event_level -= 1;
if event_level == 0 {
// We're back at the "top" so it means we're done with the summary.
end_of_summary = true;
// We surround tables with `<div>` HTML tags so this is a special case.
get_next_tag = kind == TagEnd::Table;
}
}
_ => {}
}
summary_events.push(event);
if end_of_summary {
if get_next_tag && let Some(event) = p.next() {
summary_events.push(event);
}
break;
}
}
let mut summary = String::new();
html::push_html(&mut summary, summary_events.into_iter());
if summary.is_empty() {
return (None, None);
}
let mut content = String::new();
html::push_html(&mut content, p);
if content.is_empty() { (Some(summary), None) } else { (Some(summary), Some(content)) }
}
}
@ -1882,75 +1935,82 @@ pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec<Rust
#[derive(Clone, Default, Debug)]
pub struct IdMap {
map: FxHashMap<Cow<'static, str>, usize>,
existing_footnotes: usize,
map: FxHashMap<String, usize>,
existing_footnotes: Arc<AtomicUsize>,
}
// The map is pre-initialized and cloned each time to avoid reinitializing it repeatedly.
static DEFAULT_ID_MAP: OnceLock<FxHashMap<Cow<'static, str>, usize>> = OnceLock::new();
fn init_id_map() -> FxHashMap<Cow<'static, str>, usize> {
let mut map = FxHashMap::default();
// This is the list of IDs used in JavaScript.
map.insert("help".into(), 1);
map.insert("settings".into(), 1);
map.insert("not-displayed".into(), 1);
map.insert("alternative-display".into(), 1);
map.insert("search".into(), 1);
map.insert("crate-search".into(), 1);
map.insert("crate-search-div".into(), 1);
// This is the list of IDs used in HTML generated in Rust (including the ones
// used in tera template files).
map.insert("themeStyle".into(), 1);
map.insert("settings-menu".into(), 1);
map.insert("help-button".into(), 1);
map.insert("sidebar-button".into(), 1);
map.insert("main-content".into(), 1);
map.insert("toggle-all-docs".into(), 1);
map.insert("all-types".into(), 1);
map.insert("default-settings".into(), 1);
map.insert("sidebar-vars".into(), 1);
map.insert("copy-path".into(), 1);
map.insert("rustdoc-toc".into(), 1);
map.insert("rustdoc-modnav".into(), 1);
// This is the list of IDs used by rustdoc sections (but still generated by
// rustdoc).
map.insert("fields".into(), 1);
map.insert("variants".into(), 1);
map.insert("implementors-list".into(), 1);
map.insert("synthetic-implementors-list".into(), 1);
map.insert("foreign-impls".into(), 1);
map.insert("implementations".into(), 1);
map.insert("trait-implementations".into(), 1);
map.insert("synthetic-implementations".into(), 1);
map.insert("blanket-implementations".into(), 1);
map.insert("required-associated-types".into(), 1);
map.insert("provided-associated-types".into(), 1);
map.insert("provided-associated-consts".into(), 1);
map.insert("required-associated-consts".into(), 1);
map.insert("required-methods".into(), 1);
map.insert("provided-methods".into(), 1);
map.insert("dyn-compatibility".into(), 1);
map.insert("implementors".into(), 1);
map.insert("synthetic-implementors".into(), 1);
map.insert("implementations-list".into(), 1);
map.insert("trait-implementations-list".into(), 1);
map.insert("synthetic-implementations-list".into(), 1);
map.insert("blanket-implementations-list".into(), 1);
map.insert("deref-methods".into(), 1);
map.insert("layout".into(), 1);
map.insert("aliased-type".into(), 1);
map
fn is_default_id(id: &str) -> bool {
matches!(
id,
// This is the list of IDs used in JavaScript.
"help"
| "settings"
| "not-displayed"
| "alternative-display"
| "search"
| "crate-search"
| "crate-search-div"
// This is the list of IDs used in HTML generated in Rust (including the ones
// used in tera template files).
| "themeStyle"
| "settings-menu"
| "help-button"
| "sidebar-button"
| "main-content"
| "toggle-all-docs"
| "all-types"
| "default-settings"
| "sidebar-vars"
| "copy-path"
| "rustdoc-toc"
| "rustdoc-modnav"
// This is the list of IDs used by rustdoc sections (but still generated by
// rustdoc).
| "fields"
| "variants"
| "implementors-list"
| "synthetic-implementors-list"
| "foreign-impls"
| "implementations"
| "trait-implementations"
| "synthetic-implementations"
| "blanket-implementations"
| "required-associated-types"
| "provided-associated-types"
| "provided-associated-consts"
| "required-associated-consts"
| "required-methods"
| "provided-methods"
| "dyn-compatibility"
| "implementors"
| "synthetic-implementors"
| "implementations-list"
| "trait-implementations-list"
| "synthetic-implementations-list"
| "blanket-implementations-list"
| "deref-methods"
| "layout"
| "aliased-type"
)
}
impl IdMap {
pub fn new() -> Self {
IdMap { map: DEFAULT_ID_MAP.get_or_init(init_id_map).clone(), existing_footnotes: 0 }
IdMap { map: FxHashMap::default(), existing_footnotes: Arc::new(AtomicUsize::new(0)) }
}
pub(crate) fn derive<S: AsRef<str> + ToString>(&mut self, candidate: S) -> String {
let id = match self.map.get_mut(candidate.as_ref()) {
None => candidate.to_string(),
None => {
let candidate = candidate.to_string();
if is_default_id(&candidate) {
let id = format!("{}-{}", candidate, 1);
self.map.insert(candidate.into(), 2);
id
} else {
candidate
}
}
Some(a) => {
let id = format!("{}-{}", candidate.as_ref(), *a);
*a += 1;
@ -1964,10 +2024,17 @@ impl IdMap {
/// Method to handle `existing_footnotes` increment automatically (to prevent forgetting
/// about it).
pub(crate) fn handle_footnotes<F: FnOnce(&mut Self, &mut usize)>(&mut self, closure: F) {
let mut existing_footnotes = self.existing_footnotes;
pub(crate) fn handle_footnotes<'a, T, F: FnOnce(&'a mut Self, Weak<AtomicUsize>) -> T>(
&'a mut self,
closure: F,
) -> T {
let existing_footnotes = Arc::downgrade(&self.existing_footnotes);
closure(self, &mut existing_footnotes);
self.existing_footnotes = existing_footnotes;
closure(self, existing_footnotes)
}
pub(crate) fn clear(&mut self) {
self.map.clear();
self.existing_footnotes = Arc::new(AtomicUsize::new(0));
}
}

View file

@ -1,5 +1,8 @@
//! Markdown footnote handling.
use std::fmt::Write as _;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Weak};
use pulldown_cmark::{CowStr, Event, Tag, TagEnd, html};
use rustc_data_structures::fx::FxIndexMap;
@ -8,10 +11,11 @@ use super::SpannedEvent;
/// Moves all footnote definitions to the end and add back links to the
/// references.
pub(super) struct Footnotes<'a, 'b, I> {
pub(super) struct Footnotes<'a, I> {
inner: I,
footnotes: FxIndexMap<String, FootnoteDef<'a>>,
existing_footnotes: &'b mut usize,
existing_footnotes: Arc<AtomicUsize>,
start_id: usize,
}
/// The definition of a single footnote.
@ -21,13 +25,16 @@ struct FootnoteDef<'a> {
id: usize,
}
impl<'a, 'b, I: Iterator<Item = SpannedEvent<'a>>> Footnotes<'a, 'b, I> {
pub(super) fn new(iter: I, existing_footnotes: &'b mut usize) -> Self {
Footnotes { inner: iter, footnotes: FxIndexMap::default(), existing_footnotes }
impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Footnotes<'a, I> {
pub(super) fn new(iter: I, existing_footnotes: Weak<AtomicUsize>) -> Self {
let existing_footnotes =
existing_footnotes.upgrade().expect("`existing_footnotes` was dropped");
let start_id = existing_footnotes.load(Ordering::Relaxed);
Footnotes { inner: iter, footnotes: FxIndexMap::default(), existing_footnotes, start_id }
}
fn get_entry(&mut self, key: &str) -> (&mut Vec<Event<'a>>, usize) {
let new_id = self.footnotes.len() + 1 + *self.existing_footnotes;
let new_id = self.footnotes.len() + 1 + self.start_id;
let key = key.to_owned();
let FootnoteDef { content, id } =
self.footnotes.entry(key).or_insert(FootnoteDef { content: Vec::new(), id: new_id });
@ -44,7 +51,7 @@ impl<'a, 'b, I: Iterator<Item = SpannedEvent<'a>>> Footnotes<'a, 'b, I> {
id,
// Although the ID count is for the whole page, the footnote reference
// are local to the item so we make this ID "local" when displayed.
id - *self.existing_footnotes
id - self.start_id
);
Event::Html(reference.into())
}
@ -64,7 +71,7 @@ impl<'a, 'b, I: Iterator<Item = SpannedEvent<'a>>> Footnotes<'a, 'b, I> {
}
}
impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, '_, I> {
impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, I> {
type Item = SpannedEvent<'a>;
fn next(&mut self) -> Option<Self::Item> {
@ -87,7 +94,7 @@ impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, '_, I>
// After all the markdown is emmited, emit an <hr> then all the footnotes
// in a list.
let defs: Vec<_> = self.footnotes.drain(..).map(|(_, x)| x).collect();
*self.existing_footnotes += defs.len();
self.existing_footnotes.fetch_add(defs.len(), Ordering::Relaxed);
let defs_html = render_footnotes_defs(defs);
return Some((Event::Html(defs_html.into()), 0..0));
} else {

View file

@ -2,7 +2,6 @@ use std::cell::RefCell;
use std::collections::BTreeMap;
use std::io;
use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::sync::mpsc::{Receiver, channel};
use rinja::Template;
@ -49,36 +48,49 @@ pub(crate) struct Context<'tcx> {
/// The current destination folder of where HTML artifacts should be placed.
/// This changes as the context descends into the module hierarchy.
pub(crate) dst: PathBuf,
/// A flag, which when `true`, will render pages which redirect to the
/// real location of an item. This is used to allow external links to
/// publicly reused items to redirect to the right location.
pub(super) render_redirect_pages: bool,
/// Tracks section IDs for `Deref` targets so they match in both the main
/// body and the sidebar.
pub(super) deref_id_map: DefIdMap<String>,
pub(super) deref_id_map: RefCell<DefIdMap<String>>,
/// The map used to ensure all generated 'id=' attributes are unique.
pub(super) id_map: IdMap,
pub(super) id_map: RefCell<IdMap>,
/// Shared mutable state.
///
/// Issue for improving the situation: [#82381][]
///
/// [#82381]: https://github.com/rust-lang/rust/issues/82381
pub(crate) shared: Rc<SharedContext<'tcx>>,
pub(crate) shared: SharedContext<'tcx>,
/// Collection of all types with notable traits referenced in the current module.
pub(crate) types_with_notable_traits: RefCell<FxIndexSet<clean::Type>>,
/// Contains information that needs to be saved and reset after rendering an item which is
/// not a module.
pub(crate) info: ContextInfo,
}
/// This struct contains the information that needs to be reset between each
/// [`FormatRenderer::item`] call.
///
/// When we enter a new module, we set these values for the whole module but they might be updated
/// in each child item (especially if it's a module). So to prevent these changes to impact other
/// items rendering in the same module, we need to reset them to the module's set values.
#[derive(Clone, Copy)]
pub(crate) struct ContextInfo {
/// A flag, which when `true`, will render pages which redirect to the
/// real location of an item. This is used to allow external links to
/// publicly reused items to redirect to the right location.
pub(super) render_redirect_pages: bool,
/// This flag indicates whether source links should be generated or not. If
/// the source files are present in the html rendering, then this will be
/// `true`.
pub(crate) include_sources: bool,
/// Collection of all types with notable traits referenced in the current module.
pub(crate) types_with_notable_traits: FxIndexSet<clean::Type>,
/// Field used during rendering, to know if we're inside an inlined item.
pub(crate) is_inside_inlined_module: bool,
}
// `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
#[cfg(all(not(windows), target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Context<'_>, 192);
#[cfg(all(windows, target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Context<'_>, 200);
impl ContextInfo {
fn new(include_sources: bool) -> Self {
Self { render_redirect_pages: false, include_sources, is_inside_inlined_module: false }
}
}
/// Shared mutable state used in [`Context`] and elsewhere.
pub(crate) struct SharedContext<'tcx> {
@ -163,8 +175,8 @@ impl<'tcx> Context<'tcx> {
self.shared.tcx.sess
}
pub(super) fn derive_id<S: AsRef<str> + ToString>(&mut self, id: S) -> String {
self.id_map.derive(id)
pub(super) fn derive_id<S: AsRef<str> + ToString>(&self, id: S) -> String {
self.id_map.borrow_mut().derive(id)
}
/// String representation of how to get back to the root path of the 'doc/'
@ -174,14 +186,16 @@ impl<'tcx> Context<'tcx> {
}
fn render_item(&mut self, it: &clean::Item, is_module: bool) -> String {
let mut render_redirect_pages = self.render_redirect_pages;
let mut render_redirect_pages = self.info.render_redirect_pages;
// If the item is stripped but inlined, links won't point to the item so no need to generate
// a file for it.
if it.is_stripped()
&& let Some(def_id) = it.def_id()
&& def_id.is_local()
{
if self.is_inside_inlined_module || self.shared.cache.inlined_items.contains(&def_id) {
if self.info.is_inside_inlined_module
|| self.shared.cache.inlined_items.contains(&def_id)
{
// For now we're forced to generate a redirect page for stripped items until
// `record_extern_fqn` correctly points to external items.
render_redirect_pages = true;
@ -221,24 +235,23 @@ impl<'tcx> Context<'tcx> {
};
if !render_redirect_pages {
let clone_shared = Rc::clone(&self.shared);
let mut page_buffer = Buffer::html();
print_item(self, it, &mut page_buffer);
let page = layout::Page {
css_class: tyname_s,
root_path: &self.root_path(),
static_root_path: clone_shared.static_root_path.as_deref(),
static_root_path: self.shared.static_root_path.as_deref(),
title: &title,
description: &desc,
resource_suffix: &clone_shared.resource_suffix,
resource_suffix: &self.shared.resource_suffix,
rust_logo: has_doc_flag(self.tcx(), LOCAL_CRATE.as_def_id(), sym::rust_logo),
};
let mut page_buffer = Buffer::html();
print_item(self, it, &mut page_buffer);
layout::render(
&clone_shared.layout,
&self.shared.layout,
&page,
|buf: &mut _| print_sidebar(self, it, buf),
move |buf: &mut Buffer| buf.push_buffer(page_buffer),
&clone_shared.style_files,
&self.shared.style_files,
)
} else {
if let Some(&(ref names, ty)) = self.cache().paths.get(&it.item_id.expect_def_id()) {
@ -441,6 +454,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
}
const RUN_ON_MODULE: bool = true;
type ModuleData = ContextInfo;
fn init(
krate: clean::Crate,
@ -562,13 +576,11 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
let mut cx = Context {
current: Vec::new(),
dst,
render_redirect_pages: false,
id_map,
id_map: RefCell::new(id_map),
deref_id_map: Default::default(),
shared: Rc::new(scx),
include_sources,
types_with_notable_traits: FxIndexSet::default(),
is_inside_inlined_module: false,
shared: scx,
types_with_notable_traits: RefCell::new(FxIndexSet::default()),
info: ContextInfo::new(include_sources),
};
if emit_crate {
@ -582,18 +594,15 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
Ok((cx, krate))
}
fn make_child_renderer(&self) -> Self {
Self {
current: self.current.clone(),
dst: self.dst.clone(),
render_redirect_pages: self.render_redirect_pages,
deref_id_map: Default::default(),
id_map: IdMap::new(),
shared: Rc::clone(&self.shared),
include_sources: self.include_sources,
types_with_notable_traits: FxIndexSet::default(),
is_inside_inlined_module: self.is_inside_inlined_module,
}
fn save_module_data(&mut self) -> Self::ModuleData {
self.deref_id_map.borrow_mut().clear();
self.id_map.borrow_mut().clear();
self.types_with_notable_traits.borrow_mut().clear();
self.info
}
fn restore_module_data(&mut self, info: Self::ModuleData) {
self.info = info;
}
fn after_krate(&mut self) -> Result<(), Error> {
@ -607,7 +616,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
if !root_path.ends_with('/') {
root_path.push('/');
}
let shared = Rc::clone(&self.shared);
let shared = &self.shared;
let mut page = layout::Page {
title: "List of all items in this crate",
css_class: "mod sys",
@ -754,11 +763,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
shared.fs.write(redirect_map_path, paths)?;
}
// No need for it anymore.
drop(shared);
// Flush pending errors.
Rc::get_mut(&mut self.shared).unwrap().fs.close();
self.shared.fs.close();
let nb_errors = self.shared.errors.iter().map(|err| self.tcx().dcx().err(err)).count();
if nb_errors > 0 {
Err(Error::new(io::Error::new(io::ErrorKind::Other, "I/O error"), ""))
@ -775,8 +781,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
// External crates will provide links to these structures, so
// these modules are recursed into, but not rendered normally
// (a flag on the context).
if !self.render_redirect_pages {
self.render_redirect_pages = item.is_stripped();
if !self.info.render_redirect_pages {
self.info.render_redirect_pages = item.is_stripped();
}
let item_name = item.name.unwrap();
self.dst.push(item_name.as_str());
@ -793,19 +799,19 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
self.shared.fs.write(joint_dst, buf)?;
}
}
if !self.is_inside_inlined_module {
if !self.info.is_inside_inlined_module {
if let Some(def_id) = item.def_id()
&& self.cache().inlined_items.contains(&def_id)
{
self.is_inside_inlined_module = true;
self.info.is_inside_inlined_module = true;
}
} else if !self.cache().document_hidden && item.is_doc_hidden() {
// We're not inside an inlined module anymore since this one cannot be re-exported.
self.is_inside_inlined_module = false;
self.info.is_inside_inlined_module = false;
}
// Render sidebar-items.js used throughout this module.
if !self.render_redirect_pages {
if !self.info.render_redirect_pages {
let (clean::StrippedItem(box clean::ModuleItem(ref module))
| clean::ModuleItem(ref module)) = item.kind
else {
@ -836,8 +842,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
// External crates will provide links to these structures, so
// these modules are recursed into, but not rendered normally
// (a flag on the context).
if !self.render_redirect_pages {
self.render_redirect_pages = item.is_stripped();
if !self.info.render_redirect_pages {
self.info.render_redirect_pages = item.is_stripped();
}
let buf = self.render_item(&item, false);
@ -850,7 +856,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
let joint_dst = self.dst.join(file_name);
self.shared.fs.write(joint_dst, buf)?;
if !self.render_redirect_pages {
if !self.info.render_redirect_pages {
self.shared.all.borrow_mut().append(full_path(self, &item), &item_type);
}
// If the item is a macro, redirect from the old macro URL (with !)

View file

@ -41,7 +41,6 @@ use std::collections::VecDeque;
use std::fmt::{self, Write};
use std::iter::Peekable;
use std::path::PathBuf;
use std::rc::Rc;
use std::{fs, str};
use rinja::Template;
@ -504,7 +503,7 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String {
}
fn document<'a, 'cx: 'a>(
cx: &'a mut Context<'cx>,
cx: &'a Context<'cx>,
item: &'a clean::Item,
parent: Option<&'a clean::Item>,
heading_offset: HeadingOffset,
@ -525,7 +524,7 @@ fn document<'a, 'cx: 'a>(
/// Render md_text as markdown.
fn render_markdown<'a, 'cx: 'a>(
cx: &'a mut Context<'cx>,
cx: &'a Context<'cx>,
md_text: &'a str,
links: Vec<RenderedLink>,
heading_offset: HeadingOffset,
@ -537,7 +536,7 @@ fn render_markdown<'a, 'cx: 'a>(
Markdown {
content: md_text,
links: &links,
ids: &mut cx.id_map,
ids: &mut cx.id_map.borrow_mut(),
error_codes: cx.shared.codes,
edition: cx.shared.edition(),
playground: &cx.shared.playground,
@ -552,7 +551,7 @@ fn render_markdown<'a, 'cx: 'a>(
/// docs are longer, a "Read more" link is appended to the end.
fn document_short<'a, 'cx: 'a>(
item: &'a clean::Item,
cx: &'a mut Context<'cx>,
cx: &'a Context<'cx>,
link: AssocItemLink<'a>,
parent: &'a clean::Item,
show_def_docs: bool,
@ -585,7 +584,7 @@ fn document_short<'a, 'cx: 'a>(
fn document_full_collapsible<'a, 'cx: 'a>(
item: &'a clean::Item,
cx: &'a mut Context<'cx>,
cx: &'a Context<'cx>,
heading_offset: HeadingOffset,
) -> impl fmt::Display + 'a + Captures<'cx> {
document_full_inner(item, cx, true, heading_offset)
@ -593,7 +592,7 @@ fn document_full_collapsible<'a, 'cx: 'a>(
fn document_full<'a, 'cx: 'a>(
item: &'a clean::Item,
cx: &'a mut Context<'cx>,
cx: &'a Context<'cx>,
heading_offset: HeadingOffset,
) -> impl fmt::Display + 'a + Captures<'cx> {
document_full_inner(item, cx, false, heading_offset)
@ -601,7 +600,7 @@ fn document_full<'a, 'cx: 'a>(
fn document_full_inner<'a, 'cx: 'a>(
item: &'a clean::Item,
cx: &'a mut Context<'cx>,
cx: &'a Context<'cx>,
is_collapsible: bool,
heading_offset: HeadingOffset,
) -> impl fmt::Display + 'a + Captures<'cx> {
@ -644,7 +643,7 @@ struct ItemInfo {
/// * Deprecated
/// * Required features (through the `doc_cfg` feature)
fn document_item_info(
cx: &mut Context<'_>,
cx: &Context<'_>,
item: &clean::Item,
parent: Option<&clean::Item>,
) -> ItemInfo {
@ -690,7 +689,7 @@ enum ShortItemInfo {
/// the item's documentation.
fn short_item_info(
item: &clean::Item,
cx: &mut Context<'_>,
cx: &Context<'_>,
parent: Option<&clean::Item>,
) -> Vec<ShortItemInfo> {
let mut extra_info = vec![];
@ -715,7 +714,8 @@ fn short_item_info(
if let Some(note) = note {
let note = note.as_str();
let html = MarkdownItemInfo(note, &mut cx.id_map);
let mut id_map = cx.id_map.borrow_mut();
let html = MarkdownItemInfo(note, &mut id_map);
message.push_str(": ");
message.push_str(&html.into_string());
}
@ -749,18 +749,17 @@ fn short_item_info(
// Render the list of items inside one of the sections "Trait Implementations",
// "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages).
pub(crate) fn render_impls(
cx: &mut Context<'_>,
cx: &Context<'_>,
mut w: impl Write,
impls: &[&Impl],
containing_item: &clean::Item,
toggle_open_by_default: bool,
) {
let tcx = cx.tcx();
let mut rendered_impls = impls
.iter()
.map(|i| {
let did = i.trait_did().unwrap();
let provided_trait_methods = i.inner_impl().provided_trait_methods(tcx);
let provided_trait_methods = i.inner_impl().provided_trait_methods(cx.tcx());
let assoc_link = AssocItemLink::GotoSource(did.into(), &provided_trait_methods);
let mut buffer = Buffer::new();
render_impl(
@ -906,7 +905,7 @@ fn assoc_method(
d: &clean::FnDecl,
link: AssocItemLink<'_>,
parent: ItemType,
cx: &mut Context<'_>,
cx: &Context<'_>,
render_mode: RenderMode,
) {
let tcx = cx.tcx();
@ -1071,7 +1070,7 @@ fn render_assoc_item(
item: &clean::Item,
link: AssocItemLink<'_>,
parent: ItemType,
cx: &mut Context<'_>,
cx: &Context<'_>,
render_mode: RenderMode,
) {
match &item.kind {
@ -1191,7 +1190,7 @@ fn write_impl_section_heading(w: &mut impl fmt::Write, title: &str, id: &str) {
pub(crate) fn render_all_impls(
mut w: impl Write,
cx: &mut Context<'_>,
cx: &Context<'_>,
containing_item: &clean::Item,
concrete: &[&Impl],
synthetic: &[&Impl],
@ -1225,7 +1224,7 @@ pub(crate) fn render_all_impls(
}
fn render_assoc_items<'a, 'cx: 'a>(
cx: &'a mut Context<'cx>,
cx: &'a Context<'cx>,
containing_item: &'a clean::Item,
it: DefId,
what: AssocItemRender<'a>,
@ -1240,15 +1239,14 @@ fn render_assoc_items<'a, 'cx: 'a>(
fn render_assoc_items_inner(
mut w: &mut dyn fmt::Write,
cx: &mut Context<'_>,
cx: &Context<'_>,
containing_item: &clean::Item,
it: DefId,
what: AssocItemRender<'_>,
derefs: &mut DefIdSet,
) {
info!("Documenting associated items of {:?}", containing_item.name);
let shared = Rc::clone(&cx.shared);
let cache = &shared.cache;
let cache = &cx.shared.cache;
let Some(v) = cache.impls.get(&it) else { return };
let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none());
if !non_trait.is_empty() {
@ -1276,7 +1274,7 @@ fn render_assoc_items_inner(
);
tmp_buf.write_str("</summary>");
if let Some(def_id) = type_.def_id(cx.cache()) {
cx.deref_id_map.insert(def_id, id);
cx.deref_id_map.borrow_mut().insert(def_id, id);
}
(RenderMode::ForDeref { mut_: deref_mut_ }, derived_id, r#" class="impl-items""#)
}
@ -1340,7 +1338,7 @@ fn render_assoc_items_inner(
fn render_deref_methods(
mut w: impl Write,
cx: &mut Context<'_>,
cx: &Context<'_>,
impl_: &Impl,
container_item: &clean::Item,
deref_mut: bool,
@ -1407,7 +1405,7 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) ->
}
}
pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &mut Context<'_>) -> Option<String> {
pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &Context<'_>) -> Option<String> {
let mut has_notable_trait = false;
if ty.is_unit() {
@ -1450,7 +1448,7 @@ pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &mut Context<'_>) -> O
}
if has_notable_trait {
cx.types_with_notable_traits.insert(ty.clone());
cx.types_with_notable_traits.borrow_mut().insert(ty.clone());
Some(format!(
" <a href=\"#\" class=\"tooltip\" data-notable-ty=\"{ty}\">ⓘ</a>",
ty = Escape(&format!("{:#}", ty.print(cx))),
@ -1554,7 +1552,7 @@ struct ImplRenderingParameters {
fn render_impl(
w: &mut Buffer,
cx: &mut Context<'_>,
cx: &Context<'_>,
i: &Impl,
parent: &clean::Item,
link: AssocItemLink<'_>,
@ -1563,8 +1561,7 @@ fn render_impl(
aliases: &[String],
rendering_params: ImplRenderingParameters,
) {
let shared = Rc::clone(&cx.shared);
let cache = &shared.cache;
let cache = &cx.shared.cache;
let traits = &cache.traits;
let trait_ = i.trait_did().map(|did| &traits[&did]);
let mut close_tags = <Vec<&str>>::with_capacity(2);
@ -1577,7 +1574,7 @@ fn render_impl(
fn doc_impl_item(
boring: &mut Buffer,
interesting: &mut Buffer,
cx: &mut Context<'_>,
cx: &Context<'_>,
item: &clean::Item,
parent: &clean::Item,
link: AssocItemLink<'_>,
@ -1867,7 +1864,7 @@ fn render_impl(
fn render_default_items(
boring: &mut Buffer,
interesting: &mut Buffer,
cx: &mut Context<'_>,
cx: &Context<'_>,
t: &clean::Trait,
i: &clean::Impl,
parent: &clean::Item,
@ -1938,6 +1935,23 @@ fn render_impl(
if rendering_params.toggle_open_by_default { " open" } else { "" }
);
}
let (before_dox, after_dox) = i
.impl_item
.opt_doc_value()
.map(|dox| {
Markdown {
content: &*dox,
links: &i.impl_item.links(cx),
ids: &mut cx.id_map.borrow_mut(),
error_codes: cx.shared.codes,
edition: cx.shared.edition(),
playground: &cx.shared.playground,
heading_offset: HeadingOffset::H4,
}
.split_summary_and_content()
})
.unwrap_or((None, None));
render_impl_summary(
w,
cx,
@ -1946,12 +1960,13 @@ fn render_impl(
rendering_params.show_def_docs,
use_absolute,
aliases,
&before_dox,
);
if toggled {
w.write_str("</summary>");
}
if let Some(ref dox) = i.impl_item.opt_doc_value() {
if before_dox.is_some() {
if trait_.is_none() && impl_.items.is_empty() {
w.write_str(
"<div class=\"item-info\">\
@ -1959,20 +1974,9 @@ fn render_impl(
</div>",
);
}
write!(
w,
"<div class=\"docblock\">{}</div>",
Markdown {
content: dox,
links: &i.impl_item.links(cx),
ids: &mut cx.id_map,
error_codes: cx.shared.codes,
edition: cx.shared.edition(),
playground: &cx.shared.playground,
heading_offset: HeadingOffset::H4,
}
.into_string()
);
if let Some(after_dox) = after_dox {
write!(w, "<div class=\"docblock\">{after_dox}</div>");
}
}
if !default_impl_items.is_empty() || !impl_items.is_empty() {
w.write_str("<div class=\"impl-items\">");
@ -2025,7 +2029,7 @@ fn render_rightside(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, render
pub(crate) fn render_impl_summary(
w: &mut Buffer,
cx: &mut Context<'_>,
cx: &Context<'_>,
i: &Impl,
parent: &clean::Item,
show_def_docs: bool,
@ -2033,6 +2037,7 @@ pub(crate) fn render_impl_summary(
// This argument is used to reference same type with different paths to avoid duplication
// in documentation pages for trait with automatic implementations like "Send" and "Sync".
aliases: &[String],
doc: &Option<String>,
) {
let inner_impl = i.inner_impl();
let id = cx.derive_id(get_id_for_impl(cx.tcx(), i.impl_item.item_id));
@ -2084,6 +2089,10 @@ pub(crate) fn render_impl_summary(
);
}
if let Some(doc) = doc {
write!(w, "<div class=\"docblock\">{doc}</div>");
}
w.write_str("</section>");
}
@ -2186,7 +2195,7 @@ fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String
/// implementations that are on concrete or partially generic types, only keeping implementations
/// of the form `impl<T> Trait for &T`.
pub(crate) fn get_filtered_impls_for_reference<'a>(
shared: &'a Rc<SharedContext<'_>>,
shared: &'a SharedContext<'_>,
it: &clean::Item,
) -> (Vec<&'a Impl>, Vec<&'a Impl>, Vec<&'a Impl>) {
let def_id = it.item_id.expect_def_id();
@ -2423,14 +2432,14 @@ const MAX_FULL_EXAMPLES: usize = 5;
const NUM_VISIBLE_LINES: usize = 10;
/// Generates the HTML for example call locations generated via the --scrape-examples flag.
fn render_call_locations<W: fmt::Write>(mut w: W, cx: &mut Context<'_>, item: &clean::Item) {
fn render_call_locations<W: fmt::Write>(mut w: W, cx: &Context<'_>, item: &clean::Item) {
let tcx = cx.tcx();
let def_id = item.item_id.expect_def_id();
let key = tcx.def_path_hash(def_id);
let Some(call_locations) = cx.shared.call_locations.get(&key) else { return };
// Generate a unique ID so users can link to this section for a given method
let id = cx.id_map.derive("scraped-examples");
let id = cx.derive_id("scraped-examples");
write!(
&mut w,
"<div class=\"docblock scraped-example-list\">\

View file

@ -1,7 +1,5 @@
use std::cell::{RefCell, RefMut};
use std::cmp::Ordering;
use std::fmt;
use std::rc::Rc;
use itertools::Itertools;
use rinja::Template;
@ -61,7 +59,7 @@ macro_rules! item_template {
(
$(#[$meta:meta])*
struct $name:ident<'a, 'cx> {
cx: RefCell<&'a mut Context<'cx>>,
cx: &'a Context<'cx>,
it: &'a clean::Item,
$($field_name:ident: $field_ty:ty),*,
},
@ -70,14 +68,14 @@ macro_rules! item_template {
#[derive(Template)]
$(#[$meta])*
struct $name<'a, 'cx> {
cx: RefCell<&'a mut Context<'cx>>,
cx: &'a Context<'cx>,
it: &'a clean::Item,
$($field_name: $field_ty),*
}
impl<'a, 'cx: 'a> ItemTemplate<'a, 'cx> for $name<'a, 'cx> {
fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>) {
(&self.it, self.cx.borrow_mut())
fn item_and_cx(&self) -> (&'a clean::Item, &'a Context<'cx>) {
(&self.it, &self.cx)
}
}
@ -95,8 +93,8 @@ macro_rules! item_template_methods {
(document $($rest:tt)*) => {
fn document<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
display_fn(move |f| {
let (item, mut cx) = self.item_and_mut_cx();
let v = document(*cx, item, None, HeadingOffset::H2);
let (item, cx) = self.item_and_cx();
let v = document(cx, item, None, HeadingOffset::H2);
write!(f, "{v}")
})
}
@ -105,9 +103,9 @@ macro_rules! item_template_methods {
(document_type_layout $($rest:tt)*) => {
fn document_type_layout<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
display_fn(move |f| {
let (item, cx) = self.item_and_mut_cx();
let (item, cx) = self.item_and_cx();
let def_id = item.item_id.expect_def_id();
let v = document_type_layout(*cx, def_id);
let v = document_type_layout(cx, def_id);
write!(f, "{v}")
})
}
@ -116,8 +114,8 @@ macro_rules! item_template_methods {
(render_attributes_in_pre $($rest:tt)*) => {
fn render_attributes_in_pre<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
display_fn(move |f| {
let (item, cx) = self.item_and_mut_cx();
let v = render_attributes_in_pre(item, "", &cx);
let (item, cx) = self.item_and_cx();
let v = render_attributes_in_pre(item, "", cx);
write!(f, "{v}")
})
}
@ -126,9 +124,9 @@ macro_rules! item_template_methods {
(render_assoc_items $($rest:tt)*) => {
fn render_assoc_items<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
display_fn(move |f| {
let (item, mut cx) = self.item_and_mut_cx();
let (item, cx) = self.item_and_cx();
let def_id = item.item_id.expect_def_id();
let v = render_assoc_items(*cx, item, def_id, AssocItemRender::All);
let v = render_assoc_items(cx, item, def_id, AssocItemRender::All);
write!(f, "{v}")
})
}
@ -175,7 +173,7 @@ fn print_where_clause_and_check<'a, 'tcx: 'a>(
len_before != buffer.len()
}
pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buffer) {
pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer) {
debug_assert!(!item.is_stripped());
let typ = match item.kind {
clean::ModuleItem(_) => {
@ -223,7 +221,7 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf
// this page, and this link will be auto-clicked. The `id` attribute is
// used to find the link to auto-click.
let src_href =
if cx.include_sources && !item.is_primitive() { cx.src_href(item) } else { None };
if cx.info.include_sources && !item.is_primitive() { cx.src_href(item) } else { None };
let path_components = if item.is_primitive() || item.is_keyword() {
vec![]
@ -277,13 +275,14 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf
}
// Render notable-traits.js used for all methods in this module.
if !cx.types_with_notable_traits.is_empty() {
let mut types_with_notable_traits = cx.types_with_notable_traits.borrow_mut();
if !types_with_notable_traits.is_empty() {
write!(
buf,
r#"<script type="text/json" id="notable-traits-data">{}</script>"#,
notable_traits_json(cx.types_with_notable_traits.iter(), cx)
notable_traits_json(types_with_notable_traits.iter(), cx)
);
cx.types_with_notable_traits.clear();
types_with_notable_traits.clear();
}
}
@ -308,10 +307,10 @@ fn toggle_close(mut w: impl fmt::Write) {
}
trait ItemTemplate<'a, 'cx: 'a>: rinja::Template + fmt::Display {
fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>);
fn item_and_cx(&self) -> (&'a clean::Item, &'a Context<'cx>);
}
fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: &[clean::Item]) {
fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) {
write!(w, "{}", document(cx, item, None, HeadingOffset::H2));
let mut not_stripped_items =
@ -594,7 +593,7 @@ fn extra_info_tags<'a, 'tcx: 'a>(
})
}
fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &clean::Function) {
fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::Function) {
let tcx = cx.tcx();
let header = it.fn_header(tcx).expect("printing a function which isn't a function");
debug!(
@ -649,7 +648,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle
write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
}
fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Trait) {
fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) {
let tcx = cx.tcx();
let bounds = bounds(&t.bounds, false, cx);
let required_types = t.items.iter().filter(|m| m.is_ty_associated_type()).collect::<Vec<_>>();
@ -801,7 +800,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
// Trait documentation
write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
fn trait_item(w: &mut Buffer, cx: &mut Context<'_>, m: &clean::Item, t: &clean::Item) {
fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item) {
let name = m.name.unwrap();
info!("Documenting {name} on {ty_name:?}", ty_name = t.name);
let item_type = m.type_();
@ -929,8 +928,6 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
// If there are methods directly on this trait object, render them here.
write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All));
let cloned_shared = Rc::clone(&cx.shared);
let cache = &cloned_shared.cache;
let mut extern_crates = FxIndexSet::default();
if !t.is_dyn_compatible(cx.tcx()) {
@ -950,12 +947,13 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
);
}
if let Some(implementors) = cache.implementors.get(&it.item_id.expect_def_id()) {
if let Some(implementors) = cx.shared.cache.implementors.get(&it.item_id.expect_def_id()) {
// The DefId is for the first Type found with that name. The bool is
// if any Types with the same name but different DefId have been found.
let mut implementor_dups: FxHashMap<Symbol, (DefId, bool)> = FxHashMap::default();
for implementor in implementors {
if let Some(did) = implementor.inner_impl().for_.without_borrowed_ref().def_id(cache)
if let Some(did) =
implementor.inner_impl().for_.without_borrowed_ref().def_id(&cx.shared.cache)
&& !did.is_local()
{
extern_crates.insert(did.krate);
@ -1036,7 +1034,10 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
it,
w,
&implementor_dups,
&collect_paths_for_type(implementor.inner_impl().for_.clone(), cache),
&collect_paths_for_type(
implementor.inner_impl().for_.clone(),
&cx.shared.cache,
),
);
}
w.write_str("</div>");
@ -1139,8 +1140,8 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
.chain(std::iter::once("trait.impl"))
.collect();
if let Some(did) = it.item_id.as_def_id()
&& let get_extern = { || cache.external_paths.get(&did).map(|s| &s.0) }
&& let Some(fqp) = cache.exact_paths.get(&did).or_else(get_extern)
&& let get_extern = { || cx.shared.cache.external_paths.get(&did).map(|s| &s.0) }
&& let Some(fqp) = cx.shared.cache.exact_paths.get(&did).or_else(get_extern)
{
js_src_path.extend(fqp[..fqp.len() - 1].iter().copied());
js_src_path.push_fmt(format_args!("{}.{}.js", it.type_(), fqp.last().unwrap()));
@ -1164,7 +1165,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
fn item_trait_alias(
w: &mut impl fmt::Write,
cx: &mut Context<'_>,
cx: &Context<'_>,
it: &clean::Item,
t: &clean::TraitAlias,
) {
@ -1190,7 +1191,7 @@ fn item_trait_alias(
.unwrap();
}
fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::TypeAlias) {
fn item_type_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) {
wrap_item(w, |w| {
write!(
w,
@ -1355,8 +1356,7 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c
//
// [JSONP]: https://en.wikipedia.org/wiki/JSONP
// [^115718]: https://github.com/rust-lang/rust/issues/115718
let cloned_shared = Rc::clone(&cx.shared);
let cache = &cloned_shared.cache;
let cache = &cx.shared.cache;
if let Some(target_did) = t.type_.def_id(cache) &&
let get_extern = { || cache.external_paths.get(&target_did) } &&
let Some(&(ref target_fqp, target_type)) = cache.paths.get(&target_did).or_else(get_extern) &&
@ -1380,11 +1380,11 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c
}
}
fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Union) {
fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Union) {
item_template!(
#[template(path = "item_union.html")]
struct ItemUnion<'a, 'cx> {
cx: RefCell<&'a mut Context<'cx>>,
cx: &'a Context<'cx>,
it: &'a clean::Item,
s: &'a clean::Union,
},
@ -1394,8 +1394,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
fn render_union<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
display_fn(move |f| {
let cx = self.cx.borrow_mut();
let v = render_union(self.it, Some(&self.s.generics), &self.s.fields, *cx);
let v = render_union(self.it, Some(&self.s.generics), &self.s.fields, self.cx);
write!(f, "{v}")
})
}
@ -1405,15 +1404,13 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
field: &'a clean::Item,
) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
display_fn(move |f| {
let mut cx = self.cx.borrow_mut();
let v = document(*cx, field, Some(self.it), HeadingOffset::H3);
let v = document(self.cx, field, Some(self.it), HeadingOffset::H3);
write!(f, "{v}")
})
}
fn stability_field(&self, field: &clean::Item) -> Option<String> {
let cx = self.cx.borrow();
field.stability_class(cx.tcx())
field.stability_class(self.cx.tcx())
}
fn print_ty<'b>(
@ -1421,8 +1418,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
ty: &'a clean::Type,
) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
display_fn(move |f| {
let cx = self.cx.borrow();
let v = ty.print(*cx);
let v = ty.print(&self.cx);
write!(f, "{v}")
})
}
@ -1441,7 +1437,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
}
}
ItemUnion { cx: RefCell::new(cx), it, s }.render_into(w).unwrap();
ItemUnion { cx, it, s }.render_into(w).unwrap();
}
fn print_tuple_struct_fields<'a, 'cx: 'a>(
@ -1471,7 +1467,7 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>(
})
}
fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::Enum) {
fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) {
let count_variants = e.variants().count();
wrap_item(w, |w| {
render_attributes_in_code(w, it, cx);
@ -1532,7 +1528,7 @@ fn should_show_enum_discriminant(
fn display_c_like_variant(
w: &mut Buffer,
cx: &mut Context<'_>,
cx: &Context<'_>,
item: &clean::Item,
variant: &clean::Variant,
index: VariantIdx,
@ -1557,7 +1553,7 @@ fn display_c_like_variant(
fn render_enum_fields(
mut w: &mut Buffer,
cx: &mut Context<'_>,
cx: &Context<'_>,
g: Option<&clean::Generics>,
variants: &IndexVec<VariantIdx, clean::Item>,
count_variants: usize,
@ -1621,7 +1617,7 @@ fn render_enum_fields(
fn item_variants(
w: &mut Buffer,
cx: &mut Context<'_>,
cx: &Context<'_>,
it: &clean::Item,
variants: &IndexVec<VariantIdx, clean::Item>,
enum_def_id: DefId,
@ -1743,7 +1739,7 @@ fn item_variants(
write!(w, "</div>");
}
fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Macro) {
fn item_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Macro) {
wrap_item(w, |w| {
// FIXME: Also print `#[doc(hidden)]` for `macro_rules!` if it `is_doc_hidden`.
if !t.macro_rules {
@ -1756,7 +1752,7 @@ fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
fn item_proc_macro(
w: &mut impl fmt::Write,
cx: &mut Context<'_>,
cx: &Context<'_>,
it: &clean::Item,
m: &clean::ProcMacro,
) {
@ -1790,7 +1786,7 @@ fn item_proc_macro(
write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap();
}
fn item_primitive(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item) {
fn item_primitive(w: &mut impl fmt::Write, cx: &Context<'_>, it: &clean::Item) {
let def_id = it.item_id.expect_def_id();
write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap();
if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) {
@ -1798,8 +1794,7 @@ fn item_primitive(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Ite
} else {
// We handle the "reference" primitive type on its own because we only want to list
// implementations on generic types.
let shared = Rc::clone(&cx.shared);
let (concrete, synthetic, blanket_impl) = get_filtered_impls_for_reference(&shared, it);
let (concrete, synthetic, blanket_impl) = get_filtered_impls_for_reference(&cx.shared, it);
render_all_impls(w, cx, it, &concrete, &synthetic, &blanket_impl);
}
@ -1807,7 +1802,7 @@ fn item_primitive(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Ite
fn item_constant(
w: &mut Buffer,
cx: &mut Context<'_>,
cx: &Context<'_>,
it: &clean::Item,
generics: &clean::Generics,
ty: &clean::Type,
@ -1862,7 +1857,7 @@ fn item_constant(
write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
}
fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) {
fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) {
wrap_item(w, |w| {
render_attributes_in_code(w, it, cx);
render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx);
@ -1879,7 +1874,7 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
fn item_fields(
w: &mut Buffer,
cx: &mut Context<'_>,
cx: &Context<'_>,
it: &clean::Item,
fields: &[clean::Item],
ctor_kind: Option<CtorKind>,
@ -1920,7 +1915,7 @@ fn item_fields(
fn item_static(
w: &mut impl fmt::Write,
cx: &mut Context<'_>,
cx: &Context<'_>,
it: &clean::Item,
s: &clean::Static,
safety: Option<hir::Safety>,
@ -1944,7 +1939,7 @@ fn item_static(
write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap();
}
fn item_foreign_type(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item) {
fn item_foreign_type(w: &mut impl fmt::Write, cx: &Context<'_>, it: &clean::Item) {
wrap_item(w, |buffer| {
buffer.write_str("extern {\n").unwrap();
render_attributes_in_code(buffer, it, cx);
@ -1962,7 +1957,7 @@ fn item_foreign_type(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::
.unwrap();
}
fn item_keyword(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
fn item_keyword(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
}
@ -2134,7 +2129,7 @@ impl Ord for ImplString {
}
fn render_implementor(
cx: &mut Context<'_>,
cx: &Context<'_>,
implementor: &Impl,
trait_: &clean::Item,
w: &mut Buffer,

View file

@ -1,10 +1,9 @@
use std::borrow::Cow;
use std::rc::Rc;
use rinja::Template;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::CtorKind;
use rustc_hir::def_id::DefIdSet;
use rustc_hir::def_id::{DefIdMap, DefIdSet};
use rustc_middle::ty::{self, TyCtxt};
use tracing::debug;
@ -119,17 +118,18 @@ pub(crate) mod filters {
pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
let mut ids = IdMap::new();
let mut blocks: Vec<LinkBlock<'_>> = docblock_toc(cx, it, &mut ids).into_iter().collect();
let deref_id_map = cx.deref_id_map.borrow();
match it.kind {
clean::StructItem(ref s) => sidebar_struct(cx, it, s, &mut blocks),
clean::TraitItem(ref t) => sidebar_trait(cx, it, t, &mut blocks),
clean::PrimitiveItem(_) => sidebar_primitive(cx, it, &mut blocks),
clean::UnionItem(ref u) => sidebar_union(cx, it, u, &mut blocks),
clean::EnumItem(ref e) => sidebar_enum(cx, it, e, &mut blocks),
clean::TypeAliasItem(ref t) => sidebar_type_alias(cx, it, t, &mut blocks),
clean::StructItem(ref s) => sidebar_struct(cx, it, s, &mut blocks, &deref_id_map),
clean::TraitItem(ref t) => sidebar_trait(cx, it, t, &mut blocks, &deref_id_map),
clean::PrimitiveItem(_) => sidebar_primitive(cx, it, &mut blocks, &deref_id_map),
clean::UnionItem(ref u) => sidebar_union(cx, it, u, &mut blocks, &deref_id_map),
clean::EnumItem(ref e) => sidebar_enum(cx, it, e, &mut blocks, &deref_id_map),
clean::TypeAliasItem(ref t) => sidebar_type_alias(cx, it, t, &mut blocks, &deref_id_map),
clean::ModuleItem(ref m) => {
blocks.push(sidebar_module(&m.items, &mut ids, ModuleLike::from(it)))
}
clean::ForeignTypeItem => sidebar_foreign_type(cx, it, &mut blocks),
clean::ForeignTypeItem => sidebar_foreign_type(cx, it, &mut blocks, &deref_id_map),
_ => {}
}
// The sidebar is designed to display sibling functions, modules and
@ -245,6 +245,7 @@ fn sidebar_struct<'a>(
it: &'a clean::Item,
s: &'a clean::Struct,
items: &mut Vec<LinkBlock<'a>>,
deref_id_map: &'a DefIdMap<String>,
) {
let fields = get_struct_fields_name(&s.fields);
let field_name = match s.ctor_kind {
@ -255,7 +256,7 @@ fn sidebar_struct<'a>(
if let Some(name) = field_name {
items.push(LinkBlock::new(Link::new("fields", name), "structfield", fields));
}
sidebar_assoc_items(cx, it, items);
sidebar_assoc_items(cx, it, items, deref_id_map);
}
fn sidebar_trait<'a>(
@ -263,6 +264,7 @@ fn sidebar_trait<'a>(
it: &'a clean::Item,
t: &'a clean::Trait,
blocks: &mut Vec<LinkBlock<'a>>,
deref_id_map: &'a DefIdMap<String>,
) {
fn filter_items<'a>(
items: &'a [clean::Item],
@ -313,7 +315,7 @@ fn sidebar_trait<'a>(
.into_iter()
.map(|(id, title, items)| LinkBlock::new(Link::new(id, title), "", items)),
);
sidebar_assoc_items(cx, it, blocks);
sidebar_assoc_items(cx, it, blocks, deref_id_map);
if !t.is_dyn_compatible(cx.tcx()) {
blocks.push(LinkBlock::forced(
@ -331,13 +333,17 @@ fn sidebar_trait<'a>(
}
}
fn sidebar_primitive<'a>(cx: &'a Context<'_>, it: &'a clean::Item, items: &mut Vec<LinkBlock<'a>>) {
fn sidebar_primitive<'a>(
cx: &'a Context<'_>,
it: &'a clean::Item,
items: &mut Vec<LinkBlock<'a>>,
deref_id_map: &'a DefIdMap<String>,
) {
if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) {
sidebar_assoc_items(cx, it, items);
sidebar_assoc_items(cx, it, items, deref_id_map);
} else {
let shared = Rc::clone(&cx.shared);
let (concrete, synthetic, blanket_impl) =
super::get_filtered_impls_for_reference(&shared, it);
super::get_filtered_impls_for_reference(&cx.shared, it);
sidebar_render_assoc_items(cx, &mut IdMap::new(), concrete, synthetic, blanket_impl, items);
}
@ -348,6 +354,7 @@ fn sidebar_type_alias<'a>(
it: &'a clean::Item,
t: &'a clean::TypeAlias,
items: &mut Vec<LinkBlock<'a>>,
deref_id_map: &'a DefIdMap<String>,
) {
if let Some(inner_type) = &t.inner_type {
items.push(LinkBlock::forced(Link::new("aliased-type", "Aliased type"), "type"));
@ -370,7 +377,7 @@ fn sidebar_type_alias<'a>(
}
}
}
sidebar_assoc_items(cx, it, items);
sidebar_assoc_items(cx, it, items, deref_id_map);
}
fn sidebar_union<'a>(
@ -378,10 +385,11 @@ fn sidebar_union<'a>(
it: &'a clean::Item,
u: &'a clean::Union,
items: &mut Vec<LinkBlock<'a>>,
deref_id_map: &'a DefIdMap<String>,
) {
let fields = get_struct_fields_name(&u.fields);
items.push(LinkBlock::new(Link::new("fields", "Fields"), "structfield", fields));
sidebar_assoc_items(cx, it, items);
sidebar_assoc_items(cx, it, items, deref_id_map);
}
/// Adds trait implementations into the blocks of links
@ -389,6 +397,7 @@ fn sidebar_assoc_items<'a>(
cx: &'a Context<'_>,
it: &'a clean::Item,
links: &mut Vec<LinkBlock<'a>>,
deref_id_map: &'a DefIdMap<String>,
) {
let did = it.item_id.expect_def_id();
let cache = cx.cache();
@ -433,7 +442,15 @@ fn sidebar_assoc_items<'a>(
{
let mut derefs = DefIdSet::default();
derefs.insert(did);
sidebar_deref_methods(cx, &mut blocks, impl_, v, &mut derefs, &mut used_links);
sidebar_deref_methods(
cx,
&mut blocks,
impl_,
v,
&mut derefs,
&mut used_links,
deref_id_map,
);
}
let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
@ -462,6 +479,7 @@ fn sidebar_deref_methods<'a>(
v: &[Impl],
derefs: &mut DefIdSet,
used_links: &mut FxHashSet<String>,
deref_id_map: &'a DefIdMap<String>,
) {
let c = cx.cache();
@ -501,7 +519,7 @@ fn sidebar_deref_methods<'a>(
if !ret.is_empty() {
let id = if let Some(target_def_id) = real_target.def_id(c) {
Cow::Borrowed(
cx.deref_id_map
deref_id_map
.get(&target_def_id)
.expect("Deref section without derived id")
.as_str(),
@ -531,7 +549,15 @@ fn sidebar_deref_methods<'a>(
.unwrap_or(false)
})
{
sidebar_deref_methods(cx, out, target_deref_impl, target_impls, derefs, used_links);
sidebar_deref_methods(
cx,
out,
target_deref_impl,
target_impls,
derefs,
used_links,
deref_id_map,
);
}
}
}
@ -541,6 +567,7 @@ fn sidebar_enum<'a>(
it: &'a clean::Item,
e: &'a clean::Enum,
items: &mut Vec<LinkBlock<'a>>,
deref_id_map: &'a DefIdMap<String>,
) {
let mut variants = e
.variants()
@ -550,7 +577,7 @@ fn sidebar_enum<'a>(
variants.sort_unstable();
items.push(LinkBlock::new(Link::new("variants", "Variants"), "variant", variants));
sidebar_assoc_items(cx, it, items);
sidebar_assoc_items(cx, it, items, deref_id_map);
}
pub(crate) fn sidebar_module_like(
@ -607,8 +634,9 @@ fn sidebar_foreign_type<'a>(
cx: &'a Context<'_>,
it: &'a clean::Item,
items: &mut Vec<LinkBlock<'a>>,
deref_id_map: &'a DefIdMap<String>,
) {
sidebar_assoc_items(cx, it, items);
sidebar_assoc_items(cx, it, items, deref_id_map);
}
/// Renders the trait implementations for this type

View file

@ -43,7 +43,6 @@ use crate::config::{EmitType, PathToParts, RenderOptions, ShouldMerge};
use crate::docfs::PathError;
use crate::error::Error;
use crate::formats::Impl;
use crate::formats::cache::Cache;
use crate::formats::item_type::ItemType;
use crate::html::format::Buffer;
use crate::html::layout;
@ -62,13 +61,12 @@ pub(crate) fn write_shared(
tcx: TyCtxt<'_>,
) -> Result<(), Error> {
// NOTE(EtomicBomb): I don't think we need sync here because no read-after-write?
Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(true);
cx.shared.fs.set_sync_only(true);
let lock_file = cx.dst.join(".lock");
// Write shared runs within a flock; disable thread dispatching of IO temporarily.
let _lock = try_err!(flock::Lock::new(&lock_file, true, true, true), &lock_file);
let SerializedSearchIndex { index, desc } =
build_index(krate, &mut Rc::get_mut(&mut cx.shared).unwrap().cache, tcx);
let SerializedSearchIndex { index, desc } = build_index(krate, &mut cx.shared.cache, tcx);
write_search_desc(cx, krate, &desc)?; // does not need to be merged
let crate_name = krate.name(cx.tcx());
@ -104,7 +102,7 @@ pub(crate) fn write_shared(
&cx.shared.style_files,
cx.shared.layout.css_file_extension.as_deref(),
&cx.shared.resource_suffix,
cx.include_sources,
cx.info.include_sources,
)?;
match &opt.index_page {
Some(index_page) if opt.enable_index_page => {
@ -128,7 +126,7 @@ pub(crate) fn write_shared(
}
}
Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(false);
cx.shared.fs.set_sync_only(false);
Ok(())
}
@ -597,13 +595,11 @@ impl TypeAliasPart {
krate: &Crate,
crate_name_json: &OrderedJson,
) -> Result<PartsAndLocations<Self>, Error> {
let cache = &Rc::clone(&cx.shared).cache;
let mut path_parts = PartsAndLocations::default();
let mut type_impl_collector = TypeImplCollector {
aliased_types: IndexMap::default(),
visited_aliases: FxHashSet::default(),
cache,
cx,
};
DocVisitor::visit_crate(&mut type_impl_collector, krate);
@ -625,14 +621,14 @@ impl TypeAliasPart {
// each type alias, and if it gives a different result, split the impl
for &(type_alias_fqp, type_alias_item) in type_aliases {
let mut buf = Buffer::html();
cx.id_map = Default::default();
cx.deref_id_map = Default::default();
cx.id_map.borrow_mut().clear();
cx.deref_id_map.borrow_mut().clear();
let target_did = impl_
.inner_impl()
.trait_
.as_ref()
.map(|trait_| trait_.def_id())
.or_else(|| impl_.inner_impl().for_.def_id(cache));
.or_else(|| impl_.inner_impl().for_.def_id(&cx.shared.cache));
let provided_methods;
let assoc_link = if let Some(target_did) = target_did {
provided_methods = impl_.inner_impl().provided_trait_methods(cx.tcx());
@ -720,7 +716,7 @@ impl TraitAliasPart {
}
fn get(
cx: &mut Context<'_>,
cx: &Context<'_>,
crate_name_json: &OrderedJson,
) -> Result<PartsAndLocations<Self>, Error> {
let cache = &cx.shared.cache;
@ -828,8 +824,7 @@ struct TypeImplCollector<'cx, 'cache, 'item> {
/// Map from DefId-of-aliased-type to its data.
aliased_types: IndexMap<DefId, AliasedType<'cache, 'item>>,
visited_aliases: FxHashSet<DefId>,
cache: &'cache Cache,
cx: &'cache mut Context<'cx>,
cx: &'cache Context<'cx>,
}
/// Data for an aliased type.
@ -868,7 +863,7 @@ struct AliasedTypeImpl<'cache, 'item> {
impl<'item> DocVisitor<'item> for TypeImplCollector<'_, '_, 'item> {
fn visit_item(&mut self, it: &'item Item) {
self.visit_item_recur(it);
let cache = self.cache;
let cache = &self.cx.shared.cache;
let ItemKind::TypeAliasItem(ref t) = it.kind else { return };
let Some(self_did) = it.item_id.as_def_id() else { return };
if !self.visited_aliases.insert(self_did) {

View file

@ -2,7 +2,6 @@ use std::cell::RefCell;
use std::ffi::OsStr;
use std::ops::RangeInclusive;
use std::path::{Component, Path, PathBuf};
use std::rc::Rc;
use std::{fmt, fs};
use rinja::Template;
@ -10,7 +9,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_span::{FileName, sym};
use rustc_span::{FileName, FileNameDisplayPreference, RealFileName, sym};
use tracing::info;
use crate::clean;
@ -51,8 +50,14 @@ struct LocalSourcesCollector<'a, 'tcx> {
src_root: &'a Path,
}
fn is_real_and_local(span: clean::Span, sess: &Session) -> bool {
span.cnum(sess) == LOCAL_CRATE && span.filename(sess).is_real()
fn filename_real_and_local(span: clean::Span, sess: &Session) -> Option<RealFileName> {
if span.cnum(sess) == LOCAL_CRATE
&& let FileName::Real(file) = span.filename(sess)
{
Some(file)
} else {
None
}
}
impl LocalSourcesCollector<'_, '_> {
@ -61,16 +66,8 @@ impl LocalSourcesCollector<'_, '_> {
let span = item.span(self.tcx);
let Some(span) = span else { return };
// skip all synthetic "files"
if !is_real_and_local(span, sess) {
return;
}
let filename = span.filename(sess);
let p = if let FileName::Real(file) = filename {
match file.into_local_path() {
Some(p) => p,
None => return,
}
} else {
let Some(p) = filename_real_and_local(span, sess).and_then(|file| file.into_local_path())
else {
return;
};
if self.local_sources.contains_key(&*p) {
@ -124,7 +121,7 @@ struct SourceCollector<'a, 'tcx> {
impl DocVisitor<'_> for SourceCollector<'_, '_> {
fn visit_item(&mut self, item: &clean::Item) {
if !self.cx.include_sources {
if !self.cx.info.include_sources {
return;
}
@ -136,8 +133,7 @@ impl DocVisitor<'_> for SourceCollector<'_, '_> {
// If we're not rendering sources, there's nothing to do.
// If we're including source files, and we haven't seen this file yet,
// then we need to render it out to the filesystem.
if is_real_and_local(span, sess) {
let filename = span.filename(sess);
if let Some(filename) = filename_real_and_local(span, sess) {
let span = span.inner();
let pos = sess.source_map().lookup_source_file(span.lo());
let file_span = span.with_lo(pos.start_pos).with_hi(pos.end_position());
@ -146,14 +142,14 @@ impl DocVisitor<'_> for SourceCollector<'_, '_> {
// something like that), so just don't include sources for the
// entire crate. The other option is maintaining this mapping on a
// per-file basis, but that's probably not worth it...
self.cx.include_sources = match self.emit_source(&filename, file_span) {
self.cx.info.include_sources = match self.emit_source(&filename, file_span) {
Ok(()) => true,
Err(e) => {
self.cx.shared.tcx.dcx().span_err(
span,
format!(
"failed to render source code for `{filename}`: {e}",
filename = filename.prefer_local(),
filename = filename.to_string_lossy(FileNameDisplayPreference::Local),
),
);
false
@ -169,18 +165,13 @@ impl SourceCollector<'_, '_> {
/// Renders the given filename into its corresponding HTML source file.
fn emit_source(
&mut self,
filename: &FileName,
file: &RealFileName,
file_span: rustc_span::Span,
) -> Result<(), Error> {
let p = match *filename {
FileName::Real(ref file) => {
if let Some(local_path) = file.local_path() {
local_path.to_path_buf()
} else {
unreachable!("only the current crate should have sources emitted");
}
}
_ => return Ok(()),
let p = if let Some(local_path) = file.local_path() {
local_path.to_path_buf()
} else {
unreachable!("only the current crate should have sources emitted");
};
if self.emitted_local_sources.contains(&*p) {
// We've already emitted this source
@ -197,7 +188,7 @@ impl SourceCollector<'_, '_> {
// Remove the utf-8 BOM if any
let contents = contents.strip_prefix('\u{feff}').unwrap_or(&contents);
let shared = Rc::clone(&self.cx.shared);
let shared = &self.cx.shared;
// Create the intermediate directories
let cur = RefCell::new(PathBuf::new());
let root_path = RefCell::new(PathBuf::new());
@ -234,8 +225,10 @@ impl SourceCollector<'_, '_> {
cur.push(&fname);
let title = format!("{} - source", src_fname.to_string_lossy());
let desc =
format!("Source of the Rust file `{}`.", filename.prefer_remapped_unconditionaly());
let desc = format!(
"Source of the Rust file `{}`.",
file.to_string_lossy(FileNameDisplayPreference::Remapped)
);
let page = layout::Page {
title: &title,
css_class: "src",
@ -250,12 +243,11 @@ impl SourceCollector<'_, '_> {
&page,
"",
|buf: &mut _| {
let cx = &mut self.cx;
print_src(
buf,
contents,
file_span,
cx,
self.cx,
&root_path,
highlight::DecorationInfo::default(),
SourceContext::Standalone { file_path },

View file

@ -36,6 +36,8 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\
--button-border-radius: 2px;
--toolbar-button-border-radius: 6px;
--code-block-border-radius: 6px;
--impl-items-indent: 0.3em;
--docblock-indent: 24px;
}
/* See FiraSans-LICENSE.txt for the Fira Sans license. */
@ -909,7 +911,7 @@ both the code example and the line numbers, so we need to remove the radius in t
.docblock h6 { font-size: 0.875rem; }
.docblock {
margin-left: 24px;
margin-left: var(--docblock-indent);
position: relative;
}
@ -982,7 +984,11 @@ div.where {
.item-info {
display: block;
margin-left: 24px;
margin-left: var(--docblock-indent);
}
.impl-items > .item-info {
/* Margin of docblocks + margin of impl block items. */
margin-left: calc(var(--docblock-indent) + var(--impl-items-indent));
}
.item-info code {
@ -2166,6 +2172,15 @@ details.toggle > summary:not(.hideme)::before {
left: -24px;
}
/* We indent items of an impl block to have a visual marker that these items are part
of this impl block. */
.impl-items > *:not(.item-info),
/* We also indent the first top doc comment the same to still keep an indent on the
doc block while aligning it with the impl block items. */
.implementors-toggle > .docblock {
margin-left: var(--impl-items-indent);
}
details.big-toggle > summary:not(.hideme)::before {
left: -34px;
top: 9px;
@ -2195,6 +2210,39 @@ details.toggle[open] > summary::after {
content: "Collapse";
}
details.toggle:not([open]) > summary .docblock {
max-height: calc(1.5em + 0.75em);
overflow-y: hidden;
}
details.toggle:not([open]) > summary .docblock > :first-child {
max-width: 100%;
overflow: hidden;
width: fit-content;
white-space: nowrap;
position: relative;
padding-right: 1em;
}
details.toggle:not([open]) > summary .docblock > :first-child::after {
content: "…";
position: absolute;
right: 0;
top: 0;
bottom: 0;
z-index: 1;
background-color: var(--main-background-color);
font: 1rem/1.5 "Source Serif 4", NanumBarunGothic, serif;
/* To make it look a bit better and not have it stuck to the preceding element. */
padding-left: 0.2em;
}
details.toggle:not([open]) > summary .docblock > div:first-child::after {
/* This is to make the "..." always appear at the bottom. */
padding-top: calc(1.5em + 0.75em - 1.2rem);
}
details.toggle > summary .docblock {
margin-top: 0.75em;
}
/* This is needed in docblocks to have the "▶" element to be on the same line. */
.docblock summary > * {
display: inline-block;
@ -2255,6 +2303,10 @@ If you update this line, then you also need to update the line with the same war
in src-script.js and main.js
*/
@media (max-width: 700px) {
:root {
--impl-items-indent: 0.7em;
}
/* When linking to an item with an `id` (for instance, by clicking a link in the sidebar,
or visiting a URL with a fragment like `#method.new`, we don't want the item to be obscured
by the topbar. Anything with an `id` gets scroll-margin-top equal to .mobile-topbar's size.
@ -2454,19 +2506,20 @@ in src-script.js and main.js
padding-top: 0;
}
/* Position of the "[-]" element. */
details.toggle:not(.top-doc) > summary, .impl-items > section {
details.implementors-toggle:not(.top-doc) > summary {
margin-left: 10px;
}
.impl-items > details.toggle > summary:not(.hideme)::before,
#main-content > details.toggle:not(.top-doc) > summary::before,
#main-content > div > details.toggle > summary::before {
left: -11px;
.impl-items > details.toggle > summary:not(.hideme)::before {
left: -20px;
}
/* Align summary-nested and unnested item-info gizmos. */
summary > .item-info {
margin-left: 10px;
}
.impl-items > .item-info {
margin-left: 34px;
margin-left: calc(var(--impl-items-indent) + 10px);
}
.src nav.sub {
@ -2500,24 +2553,24 @@ in src-script.js and main.js
}
@media print {
:root {
--docblock-indent: 0;
}
nav.sidebar, nav.sub, .out-of-band, a.src, #copy-path,
details.toggle[open] > summary::before, details.toggle > summary::before,
details.toggle.top-doc > summary {
display: none;
}
.docblock {
margin-left: 0;
}
main {
padding: 10px;
}
}
@media (max-width: 464px) {
.docblock {
margin-left: 12px;
:root {
--docblock-indent: 12px;
}
.docblock code {

View file

@ -321,8 +321,8 @@ fn from_clean_item(item: clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum {
MethodItem(m, _) => ItemEnum::Function(from_function(m, true, header.unwrap(), renderer)),
TyMethodItem(m) => ItemEnum::Function(from_function(m, false, header.unwrap(), renderer)),
ImplItem(i) => ItemEnum::Impl((*i).into_json(renderer)),
StaticItem(s) => ItemEnum::Static(s.into_json(renderer)),
ForeignStaticItem(s, _) => ItemEnum::Static(s.into_json(renderer)),
StaticItem(s) => ItemEnum::Static(convert_static(s, rustc_hir::Safety::Safe, renderer)),
ForeignStaticItem(s, safety) => ItemEnum::Static(convert_static(s, safety, renderer)),
ForeignTypeItem => ItemEnum::ExternType,
TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_json(renderer)),
// FIXME(generic_const_items): Add support for generic free consts
@ -831,17 +831,20 @@ impl FromClean<Box<clean::TypeAlias>> for TypeAlias {
}
}
impl FromClean<clean::Static> for Static {
fn from_clean(stat: clean::Static, renderer: &JsonRenderer<'_>) -> Self {
let tcx = renderer.tcx;
Static {
type_: (*stat.type_).into_json(renderer),
is_mutable: stat.mutability == ast::Mutability::Mut,
expr: stat
.expr
.map(|e| rendered_const(tcx, tcx.hir().body(e), tcx.hir().body_owner_def_id(e)))
.unwrap_or_default(),
}
fn convert_static(
stat: clean::Static,
safety: rustc_hir::Safety,
renderer: &JsonRenderer<'_>,
) -> Static {
let tcx = renderer.tcx;
Static {
type_: (*stat.type_).into_json(renderer),
is_mutable: stat.mutability == ast::Mutability::Mut,
is_unsafe: safety == rustc_hir::Safety::Unsafe,
expr: stat
.expr
.map(|e| rendered_const(tcx, tcx.hir().body(e), tcx.hir().body_owner_def_id(e)))
.unwrap_or_default(),
}
}

View file

@ -137,6 +137,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
}
const RUN_ON_MODULE: bool = false;
type ModuleData = ();
fn init(
krate: clean::Crate,
@ -161,8 +162,11 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
))
}
fn make_child_renderer(&self) -> Self {
self.clone()
fn save_module_data(&mut self) -> Self::ModuleData {
unreachable!("RUN_ON_MODULE = false, should never call save_module_data")
}
fn restore_module_data(&mut self, _info: Self::ModuleData) {
unreachable!("RUN_ON_MODULE = false, should never call set_back_info")
}
/// Inserts an item into the index. This should be used rather than directly calling insert on
@ -243,7 +247,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
}
fn mod_item_in(&mut self, _item: &clean::Item) -> Result<(), Error> {
unreachable!("RUN_ON_MODULE = false should never call mod_item_in")
unreachable!("RUN_ON_MODULE = false, should never call mod_item_in")
}
fn after_krate(&mut self) -> Result<(), Error> {

View file

@ -68,7 +68,7 @@ extern crate test;
// See docs in https://github.com/rust-lang/rust/blob/master/compiler/rustc/src/main.rs
// about jemalloc.
#[cfg(feature = "jemalloc")]
extern crate jemalloc_sys;
extern crate tikv_jemalloc_sys as jemalloc_sys;
use std::env::{self, VarError};
use std::io::{self, IsTerminal};
@ -76,7 +76,7 @@ use std::process;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, FatalError};
use rustc_errors::DiagCtxtHandle;
use rustc_interface::interface;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::{ErrorOutputType, RustcOptGroup, make_crate_type_option};
@ -179,7 +179,8 @@ pub fn main() {
let exit_code = rustc_driver::catch_with_exit_code(|| {
let at_args = rustc_driver::args::raw_args(&early_dcx)?;
main_args(&mut early_dcx, &at_args, using_internal_features)
main_args(&mut early_dcx, &at_args, using_internal_features);
Ok(())
});
process::exit(exit_code);
}
@ -699,13 +700,10 @@ fn usage(argv0: &str) {
);
}
/// A result type used by several functions under `main()`.
type MainResult = Result<(), ErrorGuaranteed>;
pub(crate) fn wrap_return(dcx: DiagCtxtHandle<'_>, res: Result<(), String>) -> MainResult {
pub(crate) fn wrap_return(dcx: DiagCtxtHandle<'_>, res: Result<(), String>) {
match res {
Ok(()) => dcx.has_errors().map_or(Ok(()), Err),
Err(err) => Err(dcx.err(err)),
Ok(()) => dcx.abort_if_errors(),
Err(err) => dcx.fatal(err),
}
}
@ -714,17 +712,17 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>(
renderopts: config::RenderOptions,
cache: formats::cache::Cache,
tcx: TyCtxt<'tcx>,
) -> MainResult {
) {
match formats::run_format::<T>(krate, renderopts, cache, tcx) {
Ok(_) => tcx.dcx().has_errors().map_or(Ok(()), Err),
Ok(_) => tcx.dcx().abort_if_errors(),
Err(e) => {
let mut msg =
tcx.dcx().struct_err(format!("couldn't generate documentation: {}", e.error));
tcx.dcx().struct_fatal(format!("couldn't generate documentation: {}", e.error));
let file = e.file.display().to_string();
if !file.is_empty() {
msg.note(format!("failed to create or modify \"{file}\""));
}
Err(msg.emit())
msg.emit();
}
}
}
@ -759,7 +757,7 @@ fn main_args(
early_dcx: &mut EarlyDiagCtxt,
at_args: &[String],
using_internal_features: Arc<AtomicBool>,
) -> MainResult {
) {
// Throw away the first argument, the name of the binary.
// In case of at_args being empty, as might be the case by
// passing empty argument array to execve under some platforms,
@ -770,7 +768,7 @@ fn main_args(
// the compiler with @empty_file as argv[0] and no more arguments.
let at_args = at_args.get(1..).unwrap_or_default();
let args = rustc_driver::args::arg_expand_all(early_dcx, at_args)?;
let args = rustc_driver::args::arg_expand_all(early_dcx, at_args);
let mut options = getopts::Options::new();
for option in opts() {
@ -788,7 +786,7 @@ fn main_args(
let (input, options, render_options) =
match config::Options::from_matches(early_dcx, &matches, args) {
Some(opts) => opts,
None => return Ok(()),
None => return,
};
let dcx =
@ -853,11 +851,11 @@ fn main_args(
if sess.opts.describe_lints {
rustc_driver::describe_lints(sess);
return Ok(());
return;
}
compiler.enter(|queries| {
let Ok(mut gcx) = queries.global_ctxt() else { FatalError.raise() };
let mut gcx = queries.global_ctxt();
if sess.dcx().has_errors().is_some() {
sess.dcx().fatal("Compilation failed, aborting rustdoc");
}
@ -865,7 +863,7 @@ fn main_args(
gcx.enter(|tcx| {
let (krate, render_opts, mut cache) = sess.time("run_global_ctxt", || {
core::run_global_ctxt(tcx, show_coverage, render_options, output_format)
})?;
});
info!("finished with rustc");
if let Some(options) = scrape_examples_options {
@ -884,10 +882,10 @@ fn main_args(
if show_coverage {
// if we ran coverage, bail early, we don't need to also generate docs at this point
// (also we didn't load in any of the useful passes)
return Ok(());
return;
} else if run_check {
// Since we're in "check" mode, no need to generate anything beyond this point.
return Ok(());
return;
}
info!("going to format");

View file

@ -60,8 +60,6 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -
item.kind,
clean::StructFieldItem(_)
| clean::VariantItem(_)
| clean::AssocConstItem(..)
| clean::AssocTypeItem(..)
| clean::TypeAliasItem(_)
| clean::StaticItem(_)
| clean::ConstantItem(..)
@ -69,6 +67,15 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -
| clean::ImportItem(_)
| clean::PrimitiveItem(_)
| clean::KeywordItem
| clean::ModuleItem(_)
| clean::TraitAliasItem(_)
| clean::ForeignFunctionItem(..)
| clean::ForeignStaticItem(..)
| clean::ForeignTypeItem
| clean::AssocConstItem(..)
| clean::AssocTypeItem(..)
| clean::TyAssocConstItem(..)
| clean::TyAssocTypeItem(..)
// check for trait impl
| clean::ImplItem(box clean::Impl { trait_: Some(_), .. })
)

View file

@ -2,6 +2,7 @@
use rustc_data_structures::sync::{Lock, Lrc};
use rustc_errors::emitter::Emitter;
use rustc_errors::registry::Registry;
use rustc_errors::translation::{Translate, to_fluent_args};
use rustc_errors::{Applicability, DiagCtxt, DiagInner, LazyFallbackBundle};
use rustc_parse::{source_str_to_stream, unwrap_or_emit_fatal};
@ -155,7 +156,7 @@ impl Translate for BufferEmitter {
}
impl Emitter for BufferEmitter {
fn emit_diagnostic(&mut self, diag: DiagInner) {
fn emit_diagnostic(&mut self, diag: DiagInner, _registry: &Registry) {
let mut buffer = self.buffer.borrow_mut();
let fluent_args = to_fluent_args(diag.args.iter());

View file

@ -7,7 +7,6 @@ use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::DiagCtxtHandle;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{self as hir};
use rustc_interface::interface;
use rustc_macros::{Decodable, Encodable};
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, TyCtxt};
@ -275,7 +274,7 @@ pub(crate) fn run(
tcx: TyCtxt<'_>,
options: ScrapeExamplesOptions,
bin_crate: bool,
) -> interface::Result<()> {
) {
let inner = move || -> Result<(), String> {
// Generates source files for examples
renderopts.no_emit_shared = true;
@ -329,8 +328,6 @@ pub(crate) fn run(
if let Err(e) = inner() {
tcx.dcx().fatal(e);
}
Ok(())
}
// Note: the DiagCtxt must be passed in explicitly because sess isn't available while parsing

@ -1 +1 @@
Subproject commit 104d0d16c3c7c3fef2435fef6efb2d57b70fff73
Subproject commit 1268e87bdbaed0693a9d782ccd5a21e2cab2de33

View file

@ -30,7 +30,7 @@ pub type FxHashMap<K, V> = HashMap<K, V>; // re-export for use in src/librustdoc
/// This integer is incremented with every breaking change to the API,
/// and is returned along with the JSON blob as [`Crate::format_version`].
/// Consuming code should assert that this value matches the format version(s) that it supports.
pub const FORMAT_VERSION: u32 = 36;
pub const FORMAT_VERSION: u32 = 37;
/// The root of the emitted JSON blob.
///
@ -1238,6 +1238,22 @@ pub struct Static {
///
/// It's not guaranteed that it'll match the actual source code for the initial value.
pub expr: String,
/// Is the static `unsafe`?
///
/// This is only true if it's in an `extern` block, and not explicity marked
/// as `safe`.
///
/// ```rust
/// unsafe extern {
/// static A: i32; // unsafe
/// safe static B: i32; // safe
/// }
///
/// static C: i32 = 0; // safe
/// static mut D: i32 = 0; // safe
/// ```
pub is_unsafe: bool,
}
/// A primitive type declaration. Declarations of this kind can only come from the core library.

View file

@ -14,456 +14,456 @@ nightly_branch=master
# All changes below this comment will be overridden the next time the
# tool is executed.
compiler_date=2024-10-16
compiler_date=2024-11-27
compiler_version=beta
rustfmt_date=2024-10-16
rustfmt_date=2024-11-27
rustfmt_version=nightly
dist/2024-10-16/rustc-beta-aarch64-apple-darwin.tar.gz=24719797bf50fb494c61cf4711d6bb238ea9e789a1b10d957abb23f9849a06cd
dist/2024-10-16/rustc-beta-aarch64-apple-darwin.tar.xz=5eed456f0034e2b31ed4f6089163dd5e86ecb04630371e408aca741c32d845c5
dist/2024-10-16/rustc-beta-aarch64-pc-windows-msvc.tar.gz=f337d992f4a730d39ae571d602f15d2c66ed0b6abf1b2c63112b570e855ac409
dist/2024-10-16/rustc-beta-aarch64-pc-windows-msvc.tar.xz=d22b4f26ba8b82e32114311c1f0386d0126eecffa2accab8ca9ecd6a7aa38400
dist/2024-10-16/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=047735b5c90fca9f26e5eca2a1d24dcac6fdddfddcb89c9d1e2f6d0af0199946
dist/2024-10-16/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=c70bce1fa2a6e98577683d94473ca7046e8add65b85792e9887fee4edb8bdcb7
dist/2024-10-16/rustc-beta-aarch64-unknown-linux-musl.tar.gz=4c75417b640557b35172ea384fa34a3e8da1960efdf4a40cf8d1fdbdd50ee997
dist/2024-10-16/rustc-beta-aarch64-unknown-linux-musl.tar.xz=f7f5e67b831af5fdb28266fadd7cfd9f092c066f7e7322b058d6fb2bc7f6ff77
dist/2024-10-16/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=5d94f4e51767b02ddcdafdcaba3404a3133d308fe98c7bf5145a41bde8146319
dist/2024-10-16/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=49166b4eb2e18e009ebde1e4c133adcacc3d5257fbd63b07418642d5c841957a
dist/2024-10-16/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=9e51ecc782cf9738adafd70c055ed793ab895c9616619c525cb52d7412cdf884
dist/2024-10-16/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=d60502f25273c2552997de281727b0f5914a2a97f32310f921ea714c5a1080d7
dist/2024-10-16/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=5796a33eda8d7b47c8982d3a2e425728cf681043151a291fea107b3aca9ff1a7
dist/2024-10-16/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=71fb2132822aa284cae878a76f9996092316942f84dc5a674fb8be17eb391cb0
dist/2024-10-16/rustc-beta-i686-pc-windows-gnu.tar.gz=d089cdb87961d00e7dc51c767993342a2fa704756a94c421be7f195dfa6c5293
dist/2024-10-16/rustc-beta-i686-pc-windows-gnu.tar.xz=42865105f308f7e0cf9af250b54086eaa20da8ef13e9cbf82380340a9db4ce90
dist/2024-10-16/rustc-beta-i686-pc-windows-msvc.tar.gz=5753e00d74de3ceb1af0dc533496d7db6295d673eb05aea779734a519b5f789f
dist/2024-10-16/rustc-beta-i686-pc-windows-msvc.tar.xz=dff93d0c39e8653f01248f0db05123018c63c92a1d3861935b12ad1818b00864
dist/2024-10-16/rustc-beta-i686-unknown-linux-gnu.tar.gz=4e2e06e503be7d15211dad18911ce951491d2596cef466ae8282af840184427c
dist/2024-10-16/rustc-beta-i686-unknown-linux-gnu.tar.xz=77d0d69f3e0c2b32bd1ccb73f12b5b770a1a720e7928859d454f42e611f77d67
dist/2024-10-16/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=5faa3516ecfe77f8fb21ba80e78c21a1b039f5fffae508cceffd04c8c329f152
dist/2024-10-16/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=8f086e53b3abffd7c947f5b0784f9977ed4559e654805bc3877ada99072d38e4
dist/2024-10-16/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=2147f76d151c513aaef63cb2365bb2c9a8d0eb21a6b1c7c2ff535dab0882c46a
dist/2024-10-16/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=db2c17f1f3e0af9ad56982e1396a031df07939aa04c73795f541b16161fc3bdf
dist/2024-10-16/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=e5d3fabc7902695ccf85171dd16cfe772a480dce203004da0853170450e57b1c
dist/2024-10-16/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=db2f03a41470e60a0070b4d96590ae049c23d2c0f8c07a5778023a4ecf3e52eb
dist/2024-10-16/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=49610d2df0b6ece6b2afc583db707eed0a6a12ef99a8ba0a82f9acb7c1e15fca
dist/2024-10-16/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=801a92eebf0c068c88a48129b054c4ecea143f38468ff5d53e28fd00a0fad6de
dist/2024-10-16/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=db8a9c4bc9313627d5ad2ed2ebe91b6129958254a32862aec67edee10cdf9bca
dist/2024-10-16/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=fb2f2f2acb7516d98a6abf17e84e8b36beb7179c69776d69465f1c981466321d
dist/2024-10-16/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=87effe21c4b4333769fa7b4b0fc4bd43edaabc1c8ba33e75480cb4da0d59dae9
dist/2024-10-16/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=71701db843d0974b4fc09afb65e3872faaaf66bfda258c9627576efe8f998f96
dist/2024-10-16/rustc-beta-s390x-unknown-linux-gnu.tar.gz=6485ed4c99deffdde4eee34e46b8be2eeb65a3f8f4b4eb032a4ccd9c6f4e29e7
dist/2024-10-16/rustc-beta-s390x-unknown-linux-gnu.tar.xz=e8ee8b61386d490c8e59e0c2ccb30fb7758ea0ff0b1448d5f946d9fc58496a11
dist/2024-10-16/rustc-beta-x86_64-apple-darwin.tar.gz=23e36a4892e948a6dc231d15913562f1f95f798a62a38315a6b19244aaf78385
dist/2024-10-16/rustc-beta-x86_64-apple-darwin.tar.xz=2db43b3b599eab832a13c784d3a1bc60c3222f5bfce8e112688e1478837b8c25
dist/2024-10-16/rustc-beta-x86_64-pc-windows-gnu.tar.gz=099c529cc84219ae3ed9a33dbc5265c46a01c8cffb8989e66e367078bc981eec
dist/2024-10-16/rustc-beta-x86_64-pc-windows-gnu.tar.xz=efef4dd4a40d4f96d151293031783688c84b088a5f2cdde84d931bd44aee923a
dist/2024-10-16/rustc-beta-x86_64-pc-windows-msvc.tar.gz=28633202a502121e9369e93a8cc66bcb52b2cc959d7598f9bbb8e4c840381baa
dist/2024-10-16/rustc-beta-x86_64-pc-windows-msvc.tar.xz=c7b879d2e7d7c21eafc7b8e9f18f009d2d38f91a2eafa51d25d38e3b51e17ef3
dist/2024-10-16/rustc-beta-x86_64-unknown-freebsd.tar.gz=69bdb56ac4f47fa614fa9e8be5218a492d31a423454c192ed5850f49357687e5
dist/2024-10-16/rustc-beta-x86_64-unknown-freebsd.tar.xz=36c995c1dd55ab4501f250a77f27cce34330daa2a3e74129ce389aa23b4e3a05
dist/2024-10-16/rustc-beta-x86_64-unknown-illumos.tar.gz=84bb641a5576ef0e93c7b5bae7417eae344f32271a0ebc31bb987d15316815a3
dist/2024-10-16/rustc-beta-x86_64-unknown-illumos.tar.xz=a7311a345dddc9f8cf1eab6b3e82658fadb485bd755a115d4d6ffdfb42a5625e
dist/2024-10-16/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=9def7618829111d1014e21fb0bc10abc26459e59ce61fdac5fb3b63583f472c6
dist/2024-10-16/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=97d124a65a7d7e5610901521b565ff031313685cc37a1caf89de58d952065c3c
dist/2024-10-16/rustc-beta-x86_64-unknown-linux-musl.tar.gz=101a440c383011cb4621825481582a81bfbad0ac03439542bd8d05ccb5aaf2c4
dist/2024-10-16/rustc-beta-x86_64-unknown-linux-musl.tar.xz=4148b4311ce8e1cc5dae86d5f27e207496b85e5c23a53c7bc5b05ba18918f717
dist/2024-10-16/rustc-beta-x86_64-unknown-netbsd.tar.gz=25c5c35f2acd37a7c72eb8dc546cb6e9f62b3e76e1569d188bbe2aa9b31ea3e1
dist/2024-10-16/rustc-beta-x86_64-unknown-netbsd.tar.xz=9b84ce176d4015ed8f6946ef2d42f2f601cf419d1a6477f44bd6b7c7d27c95fc
dist/2024-10-16/rust-std-beta-aarch64-apple-darwin.tar.gz=ebdf49b8d4fab00c7fb4d396c54caf5cb234389b7353856734b960f908c3cff9
dist/2024-10-16/rust-std-beta-aarch64-apple-darwin.tar.xz=4d0d5fbc235d8cc78e9997302c45916008e203ba7f02edcd061290fb9639ee8f
dist/2024-10-16/rust-std-beta-aarch64-apple-ios.tar.gz=6693f5a06df0ea5929df18b633ad6373d098db4454d0e1d35e4c19b6dd7fa4ed
dist/2024-10-16/rust-std-beta-aarch64-apple-ios.tar.xz=351a1a2a13316161edcf97238d868cf4b1b5216bdf28ca0aff5a1dba2a1258f4
dist/2024-10-16/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=f0e13e1700a1cbc1489c0a5728ce6c0f5ba1432a75ca2c0c0573b9fcf130ae9b
dist/2024-10-16/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=825550e3a2afbe15130dcf7b702ea62b3b90f8a1e0b850cd6e9a5b5dd180e72d
dist/2024-10-16/rust-std-beta-aarch64-apple-ios-sim.tar.gz=f77a6c24301c5c7165de3bf51b5b6d45e7d37a82d00446d1abbe5a5c591ca616
dist/2024-10-16/rust-std-beta-aarch64-apple-ios-sim.tar.xz=5a9507e0c06b252196203b01319355e4d246eddead60993262bd680b6a1d2315
dist/2024-10-16/rust-std-beta-aarch64-linux-android.tar.gz=eca36ae4253e5f1b51c065631a650135b71797b452a7fbf6dfa17c49a01f71d9
dist/2024-10-16/rust-std-beta-aarch64-linux-android.tar.xz=1da17cca8397bedda8b5403ddcc9f7686d7ad207daa7389a6cf80f922bac8140
dist/2024-10-16/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=1a4eea434371a7d95b473410a42d8409995119c85954f94a75b8b0a69aa3095b
dist/2024-10-16/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=cea3d7d9568d2ed86ab11d28f5a02cf36210971b798c4d61e133357c24108f6f
dist/2024-10-16/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=355fa0988a68a1a331a2794a573cd065e6fbbe8b312e187dfff59f4f4245cc5f
dist/2024-10-16/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=c93347602b0133e0da072243ba9419c95179f9f548b6284612967d7b80a42144
dist/2024-10-16/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=c4305667ed2a77764c729fe236491b239cea7c2605039c2bc28a926d21f343cc
dist/2024-10-16/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=02b6b621a1b3b91e25482400680cd38be806d7de541cf364d0ed181a92fdcbf5
dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=830e1b90ea156eee05b0c5fab514d82558e2473eb5f6bddfeafa51e7417315c2
dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=c5910437177f607439a6b18bd05b93c3965f915a0d372fb540deecf044b21880
dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=7a0f343b5fa50168a3edd0770dee148c82e43e7b2b82e2149ca22badeade3218
dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=dc4d7b3cb830451044726e72b848e529e92ec0330e610f06b07f8ed37415c3cd
dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=8a9e341e6f208d5036e4c774f68b75802c64c53c4a9381ffd5a62e9b3c486cdd
dist/2024-10-16/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=fd24b56cc9891d9a1246e62eb33f6de8385acb265ca875af79f2593ff4bd323d
dist/2024-10-16/rust-std-beta-aarch64-unknown-none.tar.gz=51a58a9f663de787ca58da8e4ed705a1099bfeca945eaab3bbce01edd45aff4b
dist/2024-10-16/rust-std-beta-aarch64-unknown-none.tar.xz=47fcf0fcdabaddde929e4828c1de1db3986af1d32a752c057ec69aee9c8f6162
dist/2024-10-16/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=207281137a1b6ec8c1df21c581c23a6db7bfdd11c550749203bbe24b9ae80019
dist/2024-10-16/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=217625e68479d09d8e63f931983e030ea9f0829cdd559ba88bf657e711c96aa6
dist/2024-10-16/rust-std-beta-aarch64-unknown-uefi.tar.gz=4c5fa8fc4e18723c4522a1e93e9e343e35f02e74fc82e6fc44951bf7e1849371
dist/2024-10-16/rust-std-beta-aarch64-unknown-uefi.tar.xz=f4440f97ebab6a79d50683169994cef569a427cb1811b85ee196432d4e2d0b38
dist/2024-10-16/rust-std-beta-arm-linux-androideabi.tar.gz=ab7dfa2b8aff6bb7514798d11970e4c09c8a4844d7408e295c547f1a87c23ea0
dist/2024-10-16/rust-std-beta-arm-linux-androideabi.tar.xz=fb9ce70893a8c89bc3e66dd6ded2e0c4813c96bd0781b6c3b420a278c53ba4cd
dist/2024-10-16/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=4650f832189a221337fc172c2ffa113ff209774949ae12e7ef159117a02e984e
dist/2024-10-16/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=f6bb5528b914311802fdb9816260e8a57531fedc5f68bef2dc6ba83d59d5ce4c
dist/2024-10-16/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=2fff203abd959498321680582bb969de89c9de4718b38e06cc91a789d7fd415e
dist/2024-10-16/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=df5cadfd5895ee1552bbcfebc40b34826481932bdde309ecb2c13f55541ca2c0
dist/2024-10-16/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=e29900d97e62c7568395191e1230fa6f98f971c1593303810f05d4db5c68592e
dist/2024-10-16/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=4455ff5a1de11281aca0df4f3f6d33d245314ce4276bda9d161bf850eda24ad6
dist/2024-10-16/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=26fcafd19aee4fcba45875d0f35aeceed7cb0a0fa070e6a2447b3d9b86170c8a
dist/2024-10-16/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=cc43780fa58e7fa1d23a3b5e2695dfd3f4ac3c02398756516c395f4546e2042d
dist/2024-10-16/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=a67a25cdaa3fabdd2b619434e3b98f05acc13f25cc7ebf8f936e7f3d1761e272
dist/2024-10-16/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=e8ee762127e02a73614e636b77d34d927f34e967cadd79158ca6ea27687c679a
dist/2024-10-16/rust-std-beta-armebv7r-none-eabi.tar.gz=7343489518ad6d354f9bfcbbc884d1c0e4fc88c4650cc68d9b9b84ee12b750b2
dist/2024-10-16/rust-std-beta-armebv7r-none-eabi.tar.xz=eef35d9c016fdb67b9825104558ca0fc1aec3af8a738636a0f24797ad270b8e6
dist/2024-10-16/rust-std-beta-armebv7r-none-eabihf.tar.gz=ed36702bbf1d45c263b8b52a06f2b4a9783c6ec78db28e00d317acd09a549977
dist/2024-10-16/rust-std-beta-armebv7r-none-eabihf.tar.xz=e4fbf4007af9858e1bebffef6bdb4c66f419b035c8fb385dc70d46ce2e312e2e
dist/2024-10-16/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=1eebca6a4ed9b04a1cd3fc57f8f75bda14cc03c8909385586c8a084e46aa96fd
dist/2024-10-16/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=0bf68ccaa22a4782f23a34b8a52ca250b183e265f12bffde7cda9ddac515040c
dist/2024-10-16/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=6f7b932bb0176fefbcc1de700a36da7c60dac609ec91e6bf351e4c42ea6fb119
dist/2024-10-16/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=a0d9397caf812fa479da6b389b653fcff451f8d54fa0545e5c908e73391b6dee
dist/2024-10-16/rust-std-beta-armv7-linux-androideabi.tar.gz=5be2ca5bd0340fa2e7ffe435081d1848ab883e46a9c0f07eee69f7dd9d08e0f6
dist/2024-10-16/rust-std-beta-armv7-linux-androideabi.tar.xz=ed563b78d4201ce29ba79cf6ebf5a3b7d8020611309e39b8790c59edcdd05b29
dist/2024-10-16/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=53f7928406a1a14dfc6774fb2704bfa9c68091b135b750c5e46e3610e00e8c72
dist/2024-10-16/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=d71cf98a8b6dfa2cc1682819d1bc5bbfe0eae819f63bb91d64e4f52bbee4158f
dist/2024-10-16/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=f65eccc2a47e34d96faa94954c738813d9b5acae351936b07df6ee2ee8592296
dist/2024-10-16/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=4f44230338a6b6bc17a8a2a80125ba18a9dedb6f9347c6e93b7f7b88c87e4468
dist/2024-10-16/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=80eae216bc5c3f77817d244f0d81cc13704894c1c7bde30c89b4f58b6049767f
dist/2024-10-16/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=b8036aee8615786593f83c3e7808eac2a59ad44ae9f5959b9719fd475b3197b0
dist/2024-10-16/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=95ca16bf6931261a62f4a3637495c02450d34fd0a0ee8abe350881b9aa0bc773
dist/2024-10-16/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=df92b9f5ec3ea09c2cc48e4c91d41ecb1fa82db87180458b1e051bbceeb4efc2
dist/2024-10-16/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=26a4426464874411bf51cf0148569c9a110681632d228dc9c9d57fbe24292e93
dist/2024-10-16/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=70ee4948185aec3b556c963ba030abbb6424e09190e31afb11d063bc2ba21664
dist/2024-10-16/rust-std-beta-armv7a-none-eabi.tar.gz=50c5b3d721cb5d83ab5f277c24eecbdbde32bdbc208bc0597830329fd19bf786
dist/2024-10-16/rust-std-beta-armv7a-none-eabi.tar.xz=9add40fc1a971f135796a8020e3ecbc6ccfa657714cee2535866f2af38fcde97
dist/2024-10-16/rust-std-beta-armv7r-none-eabi.tar.gz=d9e4695576a9f34e67804a636de6164fa7d381ac2193095cd2daa74fe148b748
dist/2024-10-16/rust-std-beta-armv7r-none-eabi.tar.xz=6592a61388b53c3d3040245b8634715026f1e2a020a118edaf43f98839537aa3
dist/2024-10-16/rust-std-beta-armv7r-none-eabihf.tar.gz=da24db2c8642e8273ef7d0e74fd32a1045ec99f5201b35d0116ba1818ab330d3
dist/2024-10-16/rust-std-beta-armv7r-none-eabihf.tar.xz=75574d203e5e15973ce1e6e12a43d6b26825844382ef76b05c4dd568912fd16b
dist/2024-10-16/rust-std-beta-i586-pc-windows-msvc.tar.gz=2e4bab4042bac836ac40e07c36c6057273d6bffaf97b1b22a64cd0876d48895d
dist/2024-10-16/rust-std-beta-i586-pc-windows-msvc.tar.xz=f335988ba2ae2853c4c8928562fa6ed81a2bbd2bd5d09dbcebd7e64cbc7d458e
dist/2024-10-16/rust-std-beta-i586-unknown-linux-gnu.tar.gz=e96921c51d49ae28871286147d589bb59eec596826d1e0eeddd928f57ed4499f
dist/2024-10-16/rust-std-beta-i586-unknown-linux-gnu.tar.xz=c17d7cbbc6bb30899a1a94f74f380bb54878b927ebe58b31592f7adb64d7b5fb
dist/2024-10-16/rust-std-beta-i586-unknown-linux-musl.tar.gz=f9030f5b2ae0411349f1f4fabd00efa3e1117ca5dc5ba60fe87f33f94e51787b
dist/2024-10-16/rust-std-beta-i586-unknown-linux-musl.tar.xz=d45b9c7c6f8de53f99b550a6d673bf8ff29e507c60ef63271d7d5ac73c765e07
dist/2024-10-16/rust-std-beta-i686-linux-android.tar.gz=2a6b9c893d2d8bbdb5900c4105fe54a988101c7d69f504e4d2983ba7aaadbbd4
dist/2024-10-16/rust-std-beta-i686-linux-android.tar.xz=94c884a0cd03fe092bdfb6fe718fd335921a82c9c2887e0e68a13fe6a183a877
dist/2024-10-16/rust-std-beta-i686-pc-windows-gnu.tar.gz=2d4a8b299987ab046536db276f3c4ea97413be5915189b9af085e4a4ba7b28ab
dist/2024-10-16/rust-std-beta-i686-pc-windows-gnu.tar.xz=eb60bf4d73fa45fe61730427287585939ff1a14efa8910877546818167b343cc
dist/2024-10-16/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=ec0f11f5cce47e6ad288393dafaa69b27fc5207194e886f0a00b4e6c3a006164
dist/2024-10-16/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=10a5c127538bc9b951c62692ca4d626cd669919d5bb2236ef6112da28db028a5
dist/2024-10-16/rust-std-beta-i686-pc-windows-msvc.tar.gz=7c9afcae592f5494ffd2baa95947b4fa5483c795e516852b463170e4797984cc
dist/2024-10-16/rust-std-beta-i686-pc-windows-msvc.tar.xz=ad9381999c1846c188d7264992c79faf413d675fdd70f22f25afcf84ed6e3b22
dist/2024-10-16/rust-std-beta-i686-unknown-freebsd.tar.gz=9b4ea3de244aaf14b6759807444bb983ec5732b119faad1c9437eb2c02d407ed
dist/2024-10-16/rust-std-beta-i686-unknown-freebsd.tar.xz=88f975eff5146af6ae548e2d7be8d402ca3d6f470b6760b75e27dedcac9f70fb
dist/2024-10-16/rust-std-beta-i686-unknown-linux-gnu.tar.gz=8a8a255695d36a86ab32abe9f37f9f6f3e9b75eee75953486d82f186d8342180
dist/2024-10-16/rust-std-beta-i686-unknown-linux-gnu.tar.xz=00a55b220767f3b692286bea728208bf665ea9a54869f82b31805b40ff56f763
dist/2024-10-16/rust-std-beta-i686-unknown-linux-musl.tar.gz=96e838064bfdace0fcd5596c50714585a221a5116e2825aba448cc1f188d0edf
dist/2024-10-16/rust-std-beta-i686-unknown-linux-musl.tar.xz=78c5be28afda04d536a634a049c175b38d46309eb4b02126ba2cda3102b92d45
dist/2024-10-16/rust-std-beta-i686-unknown-uefi.tar.gz=41a11092091b1f3b508f606978c0ac026e94614fe4b2207522b4f5f3d6c3262b
dist/2024-10-16/rust-std-beta-i686-unknown-uefi.tar.xz=a2250a5bb179549426ead55edaf3eba7626ee57a5e2c578057c3166348a47523
dist/2024-10-16/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=782998317c6c9cca107e84538ee166a37490b287efb437e5da9bf799178084b1
dist/2024-10-16/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=75b15b6d6db6f801a74419aa294b9537aa6e92b4d9d4c482e66aa6e319accee5
dist/2024-10-16/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=003a9949067435194f6a9bc6ea742876d5894ade67b5831c111826aa8ba5c2d5
dist/2024-10-16/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=5f1a4b6acfc1c82049c13ee2553ac20df016062feb368a54e44aead601105987
dist/2024-10-16/rust-std-beta-loongarch64-unknown-none.tar.gz=f5e851d27f7017832de64c134727b7cd045495ed93fece21101c1e32b4c4c5e2
dist/2024-10-16/rust-std-beta-loongarch64-unknown-none.tar.xz=289a56a0ee6087fbebed28a8d2110961c08889724d1a776a41094d5589cd112d
dist/2024-10-16/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=86cc3aa69dd4b18fc8435b6f6c1c73a24dc0b031cd79f942f6bc20a11f093f67
dist/2024-10-16/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=3e29c510424862fbd96cf61e89b6f9d64cef3c0274dea125f4af2c2a84816f5d
dist/2024-10-16/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=7506febb3ffaf1e763084d06a8dc9da096155c6a609a5c4c26feb993688f45f4
dist/2024-10-16/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=9c7e50509abfe5f0faa41eb526effa915e0799f59e5404e5a667c5f674a1ed18
dist/2024-10-16/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=6070daa8b4fc8bfb6c392767ac669a80067520c0fa85c923cb435c03a5ba6b9b
dist/2024-10-16/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=32e4064ed11bc521f26e222897ca651704e41bd42df214eb618b6fffcb909b56
dist/2024-10-16/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=51a092e812baf52f5eb7100e433fc1d5ac7cd984f8062b7d960711b9b88f1431
dist/2024-10-16/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=444bcbf145d1aff19d8e2474191ee4ff0be738c7c3b1ded12e1a9bb35d700c2f
dist/2024-10-16/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=9a4968669cb034ebdd0623f57f86a674df513abf6c01cbffce0d104447f0aacf
dist/2024-10-16/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=11e478ed0cf115eaed256e9f0f64ab9f879ea0fb26b2f520a6388d3efe705422
dist/2024-10-16/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=0476e97436699b50ce459b3c38b55425b81864162639997bc14bce33fd7ea429
dist/2024-10-16/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=f76163c6963a7f1e29cc6a348b68e3c0659b739383273029eefac4d292280a3f
dist/2024-10-16/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=f922ff15e927c047bed29d64534218d392bb584e12abdba09d9d9243613de3b4
dist/2024-10-16/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=0131845949fe27479123189bca11f2ff13aa14e0349c0901407cf65723271fad
dist/2024-10-16/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=a7898b83bf49203172e6191cc720b6b184aca6cdbe44386278fab0e6c8ca4bca
dist/2024-10-16/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=d5a4a03dfa52f732af211ae3ed3220fd76c5a2a6babada0bf94de3817e71cca9
dist/2024-10-16/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=c074043d065a85860d2f99b657035b87a1ee7fdcea53c557035a8da6fbba96ad
dist/2024-10-16/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=9a02c6c4c5cf7c57942a89da30869d7bbe2b0f5bf7374b7dec868bb5f84e00f6
dist/2024-10-16/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=1c016db6ffad0ecc552025777b2d2df5a54d6ec3a215eb2b4af0f1ccc6e45f14
dist/2024-10-16/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=399d56e3525aeb354a0c9250f070a43a7426e185960db6d8b57484f47ad11a4d
dist/2024-10-16/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=64f01a83583f4d025c95b3b2c09b86c4bae123c72a66a6a0995994d4226d34fa
dist/2024-10-16/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=794cb971242dedc2926a6b56badeffd1b4aa4f1753a22a1228eda8f336c2a5c5
dist/2024-10-16/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=1eaa20562af0921066ae04c8e1d9191ecfc4f9816a721ad2797c47b58a343084
dist/2024-10-16/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=423b35248c797ea494e6462b4a9c16e49649f0105b06b16c6137799a82f0a401
dist/2024-10-16/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=38a31b095b74cb4b678ecd797ed768f4f9f967a201b79f21b059ef8a39fbd4f9
dist/2024-10-16/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=d7a53419a2f604102bda0d0b8ee9aba790082ccb0d63c31ff28be15f37ee87d6
dist/2024-10-16/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=0cbccec64f57ca0951fe678299cf17a7aec8bb2a8d71aa7fea1a26cd720b38ca
dist/2024-10-16/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=aed7bcbb60aa5444ed8a8e1ccc7b74cc978b7e1646eb618a1899ebe61adf2c34
dist/2024-10-16/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=0cd68dad85a5cc084d8a0cddc275cd5e932e50cea18d3d622d03ecca068008e4
dist/2024-10-16/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=0873ae093594ae2d93f19003ded34d1d6d4884757e0a5a790d4766be4bd7622a
dist/2024-10-16/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=ae70c9e9edd7d83776cdd0013e081d3b16dadb2a2504037b245acc82f104112f
dist/2024-10-16/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=810c1346632064535769e8fb15ac207de45f06700e8cc9875b3971c44725a3df
dist/2024-10-16/rust-std-beta-sparcv9-sun-solaris.tar.gz=0538ccf4739439c52d6c7d99b573e7d8163a834a6163720829816d291e067217
dist/2024-10-16/rust-std-beta-sparcv9-sun-solaris.tar.xz=8064bfdddb99ba6ff202ab92e3492bd2191ea11387b930a35fcde5ac7e341c29
dist/2024-10-16/rust-std-beta-thumbv6m-none-eabi.tar.gz=a988938091594f39015783e78a334d72d41f5a3646a3da09fe7a7a0db7ec2662
dist/2024-10-16/rust-std-beta-thumbv6m-none-eabi.tar.xz=0dbf287df801225c52d4dcbfd7afdfd5c1bb8410d9342885c092a4982a0d038b
dist/2024-10-16/rust-std-beta-thumbv7em-none-eabi.tar.gz=d5b46640810193ee163ef6cf3bb8d506b6844104c3d00c033d436d79ee790dcf
dist/2024-10-16/rust-std-beta-thumbv7em-none-eabi.tar.xz=f4e7ee83d5392e2496b9d3fc1e42b45d73be3b67e723a2e62f931c11a61480af
dist/2024-10-16/rust-std-beta-thumbv7em-none-eabihf.tar.gz=0fa0ba0ca7c4e73f8b9ff2800919484cad7d902cc5e704e5aa3adb742cf6a6a0
dist/2024-10-16/rust-std-beta-thumbv7em-none-eabihf.tar.xz=ce3f3f3bc51cf79449df550b8c3fbcac588444b3234f379b93076034be6a40e7
dist/2024-10-16/rust-std-beta-thumbv7m-none-eabi.tar.gz=3b2aee46d16f38cf43cdd3f3fab78df181bab6438cb012c2caa56fa097ad1402
dist/2024-10-16/rust-std-beta-thumbv7m-none-eabi.tar.xz=3ee398b8497b7920f5d3cb18be2334ce440ec61b11e80c3ffb9eb1d898be45cc
dist/2024-10-16/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=26a67116e52dc1fcf179dd226fc28e3e21f2d2b482330d254b5882502573ee6b
dist/2024-10-16/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=d051ae1bc98060db4a2ca7fa3c3dfc6c3107632631edac41d553e4b192ccc2d3
dist/2024-10-16/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=dc34a8335b1a9dc077e38b4e4a8222d84340de604a6af547fa17bb142cd0c4da
dist/2024-10-16/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=2d5c375d09bcaad6f983d4c4e0762532feb1d3706beacbf3a8d2e4fd75bf0c71
dist/2024-10-16/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=30c73a59d9138a542337fbb2be848a152172be272a25a1ad9a28f37510e35e94
dist/2024-10-16/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=467775974be97da92015790d49cb4f89d967ed1fd7846456b4b30e20f9585501
dist/2024-10-16/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=06db2989a00b1913822cec211225b0d37143dfe1e62d394c18c04954f7396ac0
dist/2024-10-16/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=65de9bf3cfc8ac6910953b2d3b2e9de532220f692519875e7da50a6493500fe5
dist/2024-10-16/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=26a6aec0f92b238c4d75c9eda3ecbb8bf0f1628ea5bdf52941e7b5ca398ec03a
dist/2024-10-16/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=7a4b72ba1d507f418b30d7a110eb5e9025872e2398f0aa68abbef150f4c49ef1
dist/2024-10-16/rust-std-beta-wasm32-unknown-emscripten.tar.gz=cf04dc8f1df723dbca4fa3a1155dc3bced6b3c96588bf41f6bcc196b74ae19cf
dist/2024-10-16/rust-std-beta-wasm32-unknown-emscripten.tar.xz=4fd17a62d10d27c13818cc3dbe1c62aa85d9c7123b88310d12cc40939010ec97
dist/2024-10-16/rust-std-beta-wasm32-unknown-unknown.tar.gz=64ddae5e3e08ede16960f50595c4205de9962e0f5b8de9de5df1e9a8946bf66a
dist/2024-10-16/rust-std-beta-wasm32-unknown-unknown.tar.xz=0d6449807c02e1ef817fa2d378e77d9becd3a1560192bc9fdfad84cdee5cc8b3
dist/2024-10-16/rust-std-beta-wasm32-wasi.tar.gz=c4ba753891162f604effac480ded4c536f294e39768f41d7b4fea1ab28c71be3
dist/2024-10-16/rust-std-beta-wasm32-wasi.tar.xz=46a6f680f19ee2ddeb41e7aa13bb91a893ae27ae89ec41c36094f6e4db4a3e0d
dist/2024-10-16/rust-std-beta-wasm32-wasip1.tar.gz=3f89ca539044a79abd2b25f12d08ae954a7fcdcdf0288239c57d241b225776f9
dist/2024-10-16/rust-std-beta-wasm32-wasip1.tar.xz=18a922eb41f5c907bfb624d18ca882dfd569f6775105dcdc29e7c7eb49187859
dist/2024-10-16/rust-std-beta-wasm32-wasip1-threads.tar.gz=6dec5910a96e7a8e0713c109c993df44094e03fc8ac90b1a99f72dfdf84798f7
dist/2024-10-16/rust-std-beta-wasm32-wasip1-threads.tar.xz=00e21ba70b0ee2760dcd51bf68f6be74c5cf38fc301476f406bf1f1d21ae7503
dist/2024-10-16/rust-std-beta-wasm32-wasip2.tar.gz=c0b620ffb0debcd0f20155b1be250627450f14b4f62b32d9d9e4ee4c4e57cca7
dist/2024-10-16/rust-std-beta-wasm32-wasip2.tar.xz=4d14c5de2f92b67c99e6fd2342d4ee968805d9eb68d4f9d1f549bb27e866f3b0
dist/2024-10-16/rust-std-beta-x86_64-apple-darwin.tar.gz=b3ffba3cdef26174462e65847414458eba1c6aea63a78f6087497a04b427295b
dist/2024-10-16/rust-std-beta-x86_64-apple-darwin.tar.xz=1923ee9008ca30677642d1e66463555ba6fcee88dc0ed947e0ece7e4ce4efdd4
dist/2024-10-16/rust-std-beta-x86_64-apple-ios.tar.gz=e8f1cd196c5e3b10a58f640cc8bdf3d015e1b23d49724112aaa7e4019cf01107
dist/2024-10-16/rust-std-beta-x86_64-apple-ios.tar.xz=5fec3b22adc67fc6e4ef2cb873d446cb1520cfcee2ef4248e3dcc2816ada683e
dist/2024-10-16/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=852e5067d47ac896c18e424cedcb984b0b4724b7fcd05e550151de2781603737
dist/2024-10-16/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=2333f02b870c6e7b673f5e8e166bf9166c3f6d1586daafa4eeb626d8de5b305e
dist/2024-10-16/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=5c2bfde266aefa83ef9e65448900f4aa73e1d91de3719ada2512230a69090e2c
dist/2024-10-16/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=218f4a4861812e38992bf261e390e95fbe67402f89827e6ac1b68fa42c705166
dist/2024-10-16/rust-std-beta-x86_64-linux-android.tar.gz=5cd9859a22f77dffae58fb6573a8f5e23dc75bf030f54c152714777e5a01eef3
dist/2024-10-16/rust-std-beta-x86_64-linux-android.tar.xz=be754bee393794ac427718b687f5e4aaf61aa1544795ed0da0b9d20e77e45803
dist/2024-10-16/rust-std-beta-x86_64-pc-solaris.tar.gz=556f48c0ee8276bc847f3519dc0dfb72bd11cf27add709815da47f5cbb48716d
dist/2024-10-16/rust-std-beta-x86_64-pc-solaris.tar.xz=aa185610d66b606913d1102f62b62c5bbf9c5baf2e091d14d37c30b1526fb583
dist/2024-10-16/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=1a7dd15c91fb1597593b27dc0b72bc0b1a6e758935efae3c9db714cd624d7639
dist/2024-10-16/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=be18c0a1f2d0a1852c81ac1619a01d04d0c8c22472655710f643d86cb559508d
dist/2024-10-16/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=e18f210cfe890af8285da5f99cc476770daa78cddb7f8213f7f26f66111e17ef
dist/2024-10-16/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=b207877400dbfad09b6a3c2917516b63faa159f922ad03911736634ff46898d1
dist/2024-10-16/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=6f277d2e2e9a9057e2a2c8045c3949ab36ee8ed58b64829b10470e0c6b111671
dist/2024-10-16/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=51a102726ddf492dbc530437047fcb4d5e542dc4ace0e64da21c7ec79ebc001c
dist/2024-10-16/rust-std-beta-x86_64-unknown-freebsd.tar.gz=eeb6a46dd78fe3b477454c256ba8486b906e7a7ed044e686bd4f8c868265bd90
dist/2024-10-16/rust-std-beta-x86_64-unknown-freebsd.tar.xz=67e103b9742ebf2798fe8e2647a6755a1d253301fea13a5193ced5bc394b9a0c
dist/2024-10-16/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=b42fcd18458cff0ffa0902a0797e9b42cdf9475f5e84279972e4010608a14ba3
dist/2024-10-16/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=878e3950e0aefbd5c5c155f1ba2a4e8abebab10e3e77311403fc2c475e6da9df
dist/2024-10-16/rust-std-beta-x86_64-unknown-illumos.tar.gz=d72be5ca5fde3ac33da483058b8132707c93647652245864c988158e6dd70ca1
dist/2024-10-16/rust-std-beta-x86_64-unknown-illumos.tar.xz=270959bb47366b7276717b677c5303ba0d579c9fd1f98fcf3774ce033caf0015
dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=33370d376f3ecd80ddb5f614eef222c601e2df5dd18ae98ec034922790f56218
dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=061a262fe98e6e1b41df6f9f60367259d44215f528938574098ede8698985c94
dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=70328a15c8e29be07f248bb073336f06eba613c377ea4e98a1e0a4abe5e2eb6e
dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=ac389ebe5ca69cb382fd104161c9068bd8aa4d28960d578f2d925faafffb61da
dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=22d350bc0718b999d88e715cba73ef1860e1b1b8efac026f46d9050952d739b3
dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=0761b9cb94210ee40fd0dbde38cd049a9e727a73da4ebc2cf10e5db92e6860de
dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=35f975847adac17d19abba5385b951ce2015dd8b62ce4b0a716ac612808cc9d7
dist/2024-10-16/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=5a9679805c1bdfa835aee94ed0d3ed4d2b4d0b6a8e2ec4471fcbcefd331cb200
dist/2024-10-16/rust-std-beta-x86_64-unknown-netbsd.tar.gz=e4269be360d9823bccf6f7d71e4f51feeb8e955c7851d5bb6527055d709b68b7
dist/2024-10-16/rust-std-beta-x86_64-unknown-netbsd.tar.xz=58880cc63fb93bbbb78fa4268eb69b37464b429de2f007abf05f5fd7c53aec8a
dist/2024-10-16/rust-std-beta-x86_64-unknown-none.tar.gz=42c77c14c433f43a092bef5ea0cfa60aea747301a9499c66bdd81d7998a74143
dist/2024-10-16/rust-std-beta-x86_64-unknown-none.tar.xz=0cdfb3cf58d8f6db3bd65f4848aec8a431ffb4e1a5f79e56ceafe09849a96ac3
dist/2024-10-16/rust-std-beta-x86_64-unknown-redox.tar.gz=35ba471138c115ac3e1ac3560fe8590038cb6002d22a45dd92f09a868270d223
dist/2024-10-16/rust-std-beta-x86_64-unknown-redox.tar.xz=f250b60b52e2f84864406a0ef7e2f8896e1373f4f14f555a47a2019fd370f553
dist/2024-10-16/rust-std-beta-x86_64-unknown-uefi.tar.gz=7332cbab92c48611604eb13ac025b845fd0dc0bfe838a4edb02f8266a5245aeb
dist/2024-10-16/rust-std-beta-x86_64-unknown-uefi.tar.xz=7cbef4955ee702d845116c59742194b1019d67f564145cf809ecec67245ca8af
dist/2024-10-16/cargo-beta-aarch64-apple-darwin.tar.gz=59321dd2f962c7b14514fdf1ec96907c16735a03a799479055f40f17883b8b6e
dist/2024-10-16/cargo-beta-aarch64-apple-darwin.tar.xz=336c7dff9f3a1d9de819a32f62eb518dd94d45ee591afb01d329127a2146c3fb
dist/2024-10-16/cargo-beta-aarch64-pc-windows-msvc.tar.gz=00c53e3a327909882282a32850c82e4aa18508a5e355532951d380e985b75c79
dist/2024-10-16/cargo-beta-aarch64-pc-windows-msvc.tar.xz=39d09b49740b0512a84fd5351d473c5802de30721f621cf99ccd0178d8eebd60
dist/2024-10-16/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=dcb522627c49811d2e6eb133725e301089a4942da1347721ea28f2cdd670685a
dist/2024-10-16/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=b9ce402bb130d35e482ee360f8f142726ff51bac3954aeed14800eef0bd96f6d
dist/2024-10-16/cargo-beta-aarch64-unknown-linux-musl.tar.gz=670c0b78cd5c985e6bacb2bb2cc3a5a2478c2623992c4cc35d0d4c624e1b4b16
dist/2024-10-16/cargo-beta-aarch64-unknown-linux-musl.tar.xz=8a936c0c457a1d5c659611e7a69fe9934313d9ceea04c0a0eb393e28544ce7b1
dist/2024-10-16/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=10150caa2130a73443942f1dde7c849172b57b7b9e07e8939cd6c126c701d7d7
dist/2024-10-16/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=4dc0ffb898e66661a1b9844b965a0b0ca115bd6d9bb25fd5c5df022fdbeb56bf
dist/2024-10-16/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=6db24d0a3eb7de6e3d40dceccf6a92ed86e170e0c4dd2ebc9702652655ad664b
dist/2024-10-16/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=c5699a6a4ad49c34a77c94a4982b1a0ea7f6dea84d2771c24fdc05dfe9d4cdb4
dist/2024-10-16/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=f5621b39e7608e8461b559f3c3e57969e7eadce82798b395ba41e6302b2e0283
dist/2024-10-16/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=d7f62c0ac375f56d9ebbd0edbfaee4684d7d47ed8ad38bf7d25fb75a5770bdb1
dist/2024-10-16/cargo-beta-i686-pc-windows-gnu.tar.gz=b895fa9240c3a6c089cde6b08a21408b5a6f38818c4a9cf25394b17e9610da96
dist/2024-10-16/cargo-beta-i686-pc-windows-gnu.tar.xz=e26de92566339b932cdf4a4ee90464f1f3863d89534c03a3c9f9a632a278993d
dist/2024-10-16/cargo-beta-i686-pc-windows-msvc.tar.gz=ba64512c0732f5821ac4d1eb7fb53c0f340847c0cbc7dd5f88f67e03bc3f58ee
dist/2024-10-16/cargo-beta-i686-pc-windows-msvc.tar.xz=cf9872ad8ce5621faf517c2796620f24c1a99bccff7f328b7e7650e89e604b22
dist/2024-10-16/cargo-beta-i686-unknown-linux-gnu.tar.gz=23496080baad6b976f8680b7f6c856461a410a4dce5c66a41cfa220d9479cd95
dist/2024-10-16/cargo-beta-i686-unknown-linux-gnu.tar.xz=9799594bddbe1e04e1d625a6ead04efdd4749d4f0773585d21ba2be6636f0bee
dist/2024-10-16/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=5a1b95969f002c25717751337951aed39e6f6256ee58acce150d5ffaf0046300
dist/2024-10-16/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=36bab05ec8b39c7e230ed78f64b2680ea21fa9f7997c980c22edde61c0799b5a
dist/2024-10-16/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=19bfbd70b98c0bbbf29a0a796572d1661b8902132087173ca0e6aaadb4d51d09
dist/2024-10-16/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=629e42e188447a392bfc7cef5fe04c31380ee30523dc0bc33b0f3c02bd2fd82c
dist/2024-10-16/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=5d8b1daa253ebe0750e6f073b8367b053de09b4f209327d4114bfa60b2bb5602
dist/2024-10-16/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=545d7ad3b7b0b5d2ec0b4bb70b7e31dd823048d6087d6c3fa2139f307ea35fbb
dist/2024-10-16/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=2111cbc7586a1e58dc7e6e54a63157f9606f5586c7bb72ffa15f1a94284d4c97
dist/2024-10-16/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=0d6702d3ec5a6aa9dfb06d565e4e16b27cd3d445871bf2344c876d7ffe2f8a32
dist/2024-10-16/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=0f750831b518b452a2ac17c9bab3a02f30f58bba6ffcd962eed06012102c7b31
dist/2024-10-16/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=6d476e16109e9bc5dd055c537a9382ce154d2837a32bc2c165a1aec76ba1ba43
dist/2024-10-16/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=850bbca95670afa1262b5d46bb02f0bb367c83f851bc2a9817f8bf2eda9bd2ef
dist/2024-10-16/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=f42b3b5cb506886bcfc92c0a7f3dd3d0668bdda0f2db657b98becb4c0e99bfd1
dist/2024-10-16/cargo-beta-s390x-unknown-linux-gnu.tar.gz=f3a8541b3e6c12f350fcfbf43a8efb2a8bb48a62e055d9dc522d568b94476f43
dist/2024-10-16/cargo-beta-s390x-unknown-linux-gnu.tar.xz=12c5411791c715562c99dd211095c9924142053d510e17e6ec50b7b8b927eda1
dist/2024-10-16/cargo-beta-x86_64-apple-darwin.tar.gz=95885bfcf5fc1de80d0f9b5415dd261136d5577b7d61716c184a6c6379acca21
dist/2024-10-16/cargo-beta-x86_64-apple-darwin.tar.xz=881c9d88bf2a848f5b5cd61d18068e2dda3542a65e93ab373e3a047cc30369d2
dist/2024-10-16/cargo-beta-x86_64-pc-windows-gnu.tar.gz=c04ca1768c5925d5c7e19d5f232adbda355469974b19a2a130a6967db94b56c3
dist/2024-10-16/cargo-beta-x86_64-pc-windows-gnu.tar.xz=bc02593e98f5393ce2032fb605ec2bc053a1a19311a5a80d27c3a552ec8b968b
dist/2024-10-16/cargo-beta-x86_64-pc-windows-msvc.tar.gz=8ffb930c33ad454806f2f61a10949a3fa5b92b9313454927dbd76928955ed7f2
dist/2024-10-16/cargo-beta-x86_64-pc-windows-msvc.tar.xz=ef0bbe8512b3dc9bdc9f3a47abf2834bcde1fd7f59e319f7c7040b7100ba1f8a
dist/2024-10-16/cargo-beta-x86_64-unknown-freebsd.tar.gz=eb21f7739dbd7c120dc9552360e8aa6e1e0eee14d80ea16e3dcecb9e94efe7c0
dist/2024-10-16/cargo-beta-x86_64-unknown-freebsd.tar.xz=9e287f3d0c7e402dbc121cd737fd2360dfcd97fa886770aae93c07474494bb77
dist/2024-10-16/cargo-beta-x86_64-unknown-illumos.tar.gz=1cb86b6953ec99e95d92d61ead263021d16921cfe6152b6331efb838c46be85c
dist/2024-10-16/cargo-beta-x86_64-unknown-illumos.tar.xz=c356e671ca97dcb4d945567e33f06911d5269fdebc19fe83a9313f574d446576
dist/2024-10-16/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=7613e679837e2769b9e8df5b8785fdb7e51665379e64547bae9d6015eb8e45c0
dist/2024-10-16/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=39ae7207f84ee3da16ee11271070e8b82d2991cde29771d5154bb2957d9beccc
dist/2024-10-16/cargo-beta-x86_64-unknown-linux-musl.tar.gz=4dfaa69f4377bb724eb7d1990aea7ac219a960b690601769f8e06b72f59f86b4
dist/2024-10-16/cargo-beta-x86_64-unknown-linux-musl.tar.xz=4cf72f3f0048e8cfb2b05566cbc1d76e9730cf1f71f9d0f3a71bd9379f30b08c
dist/2024-10-16/cargo-beta-x86_64-unknown-netbsd.tar.gz=e1d3ff748dcf1777bc2d999ec82f0b8a67295f91a9cb07a9c1123cd5424928c3
dist/2024-10-16/cargo-beta-x86_64-unknown-netbsd.tar.xz=7e21e89e218118d536d489d16e77e667df7ba7c809135ba179e7097a2243df5d
dist/2024-10-16/clippy-beta-aarch64-apple-darwin.tar.gz=244ed83cac923e00647cdd3aab9d0479cf420991e9e06eee5ffd8acc9e5a199e
dist/2024-10-16/clippy-beta-aarch64-apple-darwin.tar.xz=6dd93a671fca0efb2d3b8cc461aba66483624327a382fd714a526832034c8438
dist/2024-10-16/clippy-beta-aarch64-pc-windows-msvc.tar.gz=56710fa9c7d46fb881903e08e407c258e3ffc75ce3de0226dcdc3709dc59180e
dist/2024-10-16/clippy-beta-aarch64-pc-windows-msvc.tar.xz=6ee782709786c310fb1e887cc576e7e61b0a4b120f6a46c7dea1e2f2bf7dad1d
dist/2024-10-16/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=06f0ee2195349921d1ae791fa1628fceaa7adb377968fa09dbe17aa77c762a47
dist/2024-10-16/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=6e792e91db8b54e0cfb9eaed8187b5202ac5d5735ed0f73080a6a73bf15ce683
dist/2024-10-16/clippy-beta-aarch64-unknown-linux-musl.tar.gz=bde52962b121472cd1b755c506b9362ff88ec582cb3fe9d307948c51f4d96f1c
dist/2024-10-16/clippy-beta-aarch64-unknown-linux-musl.tar.xz=70a06d5b8175d078bd246adf45f3058d362f0b128f1dc11d3797840b28692bf5
dist/2024-10-16/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=ab8b54d8436dbc6af279a048d2b75eea9eabfa369f23c51fc1c47388f642a755
dist/2024-10-16/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=a2715009144defc9aea3ff0d6a15485d8feedd37b333658470d479600fe87ffd
dist/2024-10-16/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=a1863b47208051a231f9571bdac3628d8afdfca7eac3b1cb7a04a843c176ae80
dist/2024-10-16/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=a5926e8e3e2867a8fa87db77dc26bd18734f84a4a685374dda07d50d21068f62
dist/2024-10-16/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=f70eabd386aac93c676485bd42845e62b34c034b8710bf0db24a440c03b15bce
dist/2024-10-16/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=cfde41ebe7398d0858bf507b9322c5f4959becd5a3a4624027b4bf3321730a29
dist/2024-10-16/clippy-beta-i686-pc-windows-gnu.tar.gz=3d988126d6a0ed9133b73b8aea3b16d6355db8ad83254a7499f7dc3b414d62f8
dist/2024-10-16/clippy-beta-i686-pc-windows-gnu.tar.xz=6efe88aab2daa0c7df17bbb449c2b815e085ca7e859b17bb578978d18ca2ea04
dist/2024-10-16/clippy-beta-i686-pc-windows-msvc.tar.gz=2c2eb32ebe3ec89a985c07ce87cc1dbc627f5f8588aeac72fd381c6e19034095
dist/2024-10-16/clippy-beta-i686-pc-windows-msvc.tar.xz=fe2d2ae70e0ce102794450d4259b706d3bda2c5b05bd21a863b2ecd8ed54274b
dist/2024-10-16/clippy-beta-i686-unknown-linux-gnu.tar.gz=0d633381b174f04523f13cc574e79af5041a231aa61b0befc406c7e3ccb0ebf3
dist/2024-10-16/clippy-beta-i686-unknown-linux-gnu.tar.xz=029558aecdd4862dc74ce9726a462f1d34a7e2a6eda5bf791995dfd6933096e7
dist/2024-10-16/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=2bdaa7f730f30db62ed0661f135227c54249786a78a8022428ead03766c9e29b
dist/2024-10-16/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=2a4f5982eac9cb5e8372d35c13a7832d532a31e5c38d13b0643d16832e1e341e
dist/2024-10-16/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=a9a1fc5b74e19a567c45ce1789c7bfd50b28774bca8320886108e4a18a1d7765
dist/2024-10-16/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=9e957652f80b2de14c5a8f5faaa5662d0ebd26e18b2bc5d248587d72413e483b
dist/2024-10-16/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=a9fa9caea0f784ed096b3ff204a8261126102e05456c52d544c7036f9ee30c41
dist/2024-10-16/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=0e3d3472e3e73b02aca8797ecaa2471e472d361b0c44126e4bfc2d25a8fad96c
dist/2024-10-16/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=211c52eed69942aed1e6b1fb4799232ea4fd3f898a44a4bb6343336e89dfec74
dist/2024-10-16/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=8c07b34223e465e17094b7e20efdbf8ec6ef5aa042485d3cfbc6ef58dbca0be9
dist/2024-10-16/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=b3fc3cc6e81ef118eada3c01fc3535dfc622b92377d8e735f80d7661b4b847fb
dist/2024-10-16/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=e885c534589fac79046bb31b92aefe7674dee13c8df1a456e91ca63e9d92c6d5
dist/2024-10-16/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=fcfbf29d105ade4a6d7537dc44d01c6de2de70d066afd8ac3af58bf3bcb6f7d0
dist/2024-10-16/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=a5425df8cd724fd992de26434090e157e9d148d063161bfb43789d6b4234ad02
dist/2024-10-16/clippy-beta-s390x-unknown-linux-gnu.tar.gz=ab96fc1c538a9a526124bc2cf3e97edd655f29f8d6d310b3b5f017cfbe6311e3
dist/2024-10-16/clippy-beta-s390x-unknown-linux-gnu.tar.xz=096de4e9f80f40a294dfd1ba32e9de038c3449b2760189a5c9e46cf8e36dc0d6
dist/2024-10-16/clippy-beta-x86_64-apple-darwin.tar.gz=5614651ef2acd5ce1d43cc2504d353e471d9c8c425c16e3649f81e1cef44b86f
dist/2024-10-16/clippy-beta-x86_64-apple-darwin.tar.xz=26e39442af2251c52bcd275c7ae25a88211ec2f582bbe7a29724f816768c9781
dist/2024-10-16/clippy-beta-x86_64-pc-windows-gnu.tar.gz=b2626513cbcd9b1456dce8543c2b11458eb052434f9ca84a6e926a77e5be2362
dist/2024-10-16/clippy-beta-x86_64-pc-windows-gnu.tar.xz=87403c11e1b92bbbc2651183b2b480c41d9c7e0fa6f08551702c6ab308fbbf5e
dist/2024-10-16/clippy-beta-x86_64-pc-windows-msvc.tar.gz=929029e67d34bc813061c524490b8f0030d31097fc1fd439acd4d8c3545589a1
dist/2024-10-16/clippy-beta-x86_64-pc-windows-msvc.tar.xz=1584df60f086c6af01f06023236f612bf59be9d5b991bd09ed66f4c505737533
dist/2024-10-16/clippy-beta-x86_64-unknown-freebsd.tar.gz=d5ee8cfefbf164d33529f1a777437f49216e93173a2ac04b605e74fea89fc6a3
dist/2024-10-16/clippy-beta-x86_64-unknown-freebsd.tar.xz=9469aead14fc03ebe984e51bbee0db6d1cd8e877b67ca361c44939e2464a95fe
dist/2024-10-16/clippy-beta-x86_64-unknown-illumos.tar.gz=79bd918b2a391cbeb885b7075b1e0534054c81784c332a2aa8539d0e1cd15f69
dist/2024-10-16/clippy-beta-x86_64-unknown-illumos.tar.xz=16b808026a4fdfaa85a4ac01b01b4fc79c4824a651bd4e412e4ee9b0011eca4c
dist/2024-10-16/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=62224af7a1831140fc3f06e7e918191e9443751549ec5c96afdcb3ffb5b18e06
dist/2024-10-16/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=78bab115fa696fc95d911655575032fc9af324c8b6df136044f11681239e5c41
dist/2024-10-16/clippy-beta-x86_64-unknown-linux-musl.tar.gz=1a76ea2b1596acd396585d78d01be5d3b795641d7b20f84379cd2c344e7536e9
dist/2024-10-16/clippy-beta-x86_64-unknown-linux-musl.tar.xz=63ac980b41b0a3b744d94727af6ee1679b8bc4c50db4ef68402d0253b1852ffb
dist/2024-10-16/clippy-beta-x86_64-unknown-netbsd.tar.gz=eba61354aecfea64815a68b569122e029501d85876d37f5ea4119f36f932e146
dist/2024-10-16/clippy-beta-x86_64-unknown-netbsd.tar.xz=37f9395e78a2bf2977b38929b9511e9668f26e23705d025609f028b282aeaee2
dist/2024-10-16/rustfmt-nightly-aarch64-apple-darwin.tar.gz=05cc308cd0c35063b43a45dab3e84001e2d580b10431c74899a86cd8971e5b36
dist/2024-10-16/rustfmt-nightly-aarch64-apple-darwin.tar.xz=aede50889786bc1e902162b9347cf59ee67b15e902b0ed78d7187d3c24a7c4a0
dist/2024-10-16/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=1c25ee283dbc720b471d435ed952e6d794ecacafd4c889a2ad8d43725cba8ded
dist/2024-10-16/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=67602978481a53b0b4681523d94bf79ad731a369cc088c3b0adf8e7d54b1fbce
dist/2024-10-16/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=ed7c9c38071f9d1e632104ff1d9a9407efec99d74eabd127db795c56e84b9d73
dist/2024-10-16/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=65ee60bfefa1334cece9f5da72789d90b4b5918e7afea2b47aa4d1450d9a1237
dist/2024-10-16/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=e92d5ddf80c94bdc34697bec4d7a1b1ea677e5fc6c68c41059a7829e53e95505
dist/2024-10-16/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=2f1737178817318d1543deabd865aa83a1f395a36cc83e3717157b4dad827f22
dist/2024-10-16/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=a4be0eb92a011ed940db67973d5fb62c4b5d3fdd52a08981223c5fa5278826b5
dist/2024-10-16/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=a47b2dab4f20f53e6c29fbce06383144a67ece61a63f33c3fb86beaabfe4bce5
dist/2024-10-16/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=7bfef0a8b7cb4a905ad145311c320a8ccb2048e806ef68688a1423009770b35a
dist/2024-10-16/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=d944161b92bdd74f3ba533b94b67a3a361a01b82fa5c156710608f00c46913ec
dist/2024-10-16/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=46a46ad32e2829550e301a84212f057faf21bf67ff6862f77f11cb0e13f80453
dist/2024-10-16/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=d917336a949ad5a5f0fcfe1ef261d87d4dcbde22b467258543c50715a9041d64
dist/2024-10-16/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=38a9cd401774ff1d832e536ed0aca9a3f0d5593814bd6db9ba4f8341a5545fd3
dist/2024-10-16/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=fa2194663d11d517bbd67c157fc40cf67149246c391e9b8adf0a46c2eb96c860
dist/2024-10-16/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=c5271c244d8055401d3d3a97873064b93915dbcc52108cb9b61381af1ebe99ad
dist/2024-10-16/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=56c6a0cedf3ec4667d65a209477cfe0d395e534654b49e28efbd3836e8a0dae7
dist/2024-10-16/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=c4325b80bfc63dc58c4632ede188efdc94aa4cad49abfa4e57d81faad673a35c
dist/2024-10-16/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=35b4fba91cad3bf9e627d59baf1f1864e30d002b05696c61498e73fd0e0f299f
dist/2024-10-16/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=b2f856cc81be2c6f2c4250ec88cbab0a51c3d59e73fefd66cae9b1a91a32b0bb
dist/2024-10-16/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=1b1a40377a8a13b74f62f5bb382cb8056930c543b97261d32613c53826c758da
dist/2024-10-16/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=98b1f0fc4f45eae47a6cae7e7d4d9734979d8f860c7c96da281fa1d9ed3ca39f
dist/2024-10-16/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=bae7dbd1342d5aa89c335f1dcdac0d93f5cd8198ce9f869ef4c32dba8bc6c0d7
dist/2024-10-16/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=cb5dc166002aba8a95f7e10d2d9e93a66d51483540c7e733b528bfccdbc74d9f
dist/2024-10-16/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=c070a48d0aad7ce42cfe5eba9477a0f54a9e04c9ec5c770e91bd2db55d0d764a
dist/2024-10-16/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=424c0d9a047ac228cfed286d0a2936b857e1c575ddebd931ca634e0501c125da
dist/2024-10-16/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=b067b3d095a5b53191ff148d0e89baed0b53c2099142d885961220548b904c52
dist/2024-10-16/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=01acab58a327ee34d100e67a4a40a9efb66a64d478d6bcaaf94ce35874296c42
dist/2024-10-16/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=c1a715f7502ef54a236d4ebe15488ec4c1c5cc5b1c50eea416a5b9c57de66f53
dist/2024-10-16/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=cb014573a52f2d6776e47f3f728ae1e8b05feac2274c5916b1545675e658fc15
dist/2024-10-16/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=5abf6bf36bcb57c0492e9bb4953ef78a61acf347d20ab788b4b31da44ae3bd39
dist/2024-10-16/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=0bee2c4ea3f8ba07c189f7e2e0df1b2627b7bb638823fde2839d46a353e0480a
dist/2024-10-16/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=df352612d69dff13b59da185581a48062e54ee07161b1fe205b92d0687a4e896
dist/2024-10-16/rustfmt-nightly-x86_64-apple-darwin.tar.gz=b7b44f5fb37fac58a83c2220a68c251513fcca96c51a71b189152a78cf095cf9
dist/2024-10-16/rustfmt-nightly-x86_64-apple-darwin.tar.xz=f5876f1d8181880e4ecb71eaa2477b0431dd0bbb45e6a4da8f20bc31426cb43d
dist/2024-10-16/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=cae33e30d7b2e5589a6fe681345f6edbf406aa803d0d521ea182a575ee32dca2
dist/2024-10-16/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=21324d7c6949bd12c841db8904d9485dd709f8c324e7aea31f2a9eb2a32844c0
dist/2024-10-16/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=cfccffb90721492cc79212ba49dd88361c6d38eab24ca4fbfd8110c2eefea001
dist/2024-10-16/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=05c528e683c40467ed3911ec5f852914e117fd71e8a0826f17d91295d4f1b047
dist/2024-10-16/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=97cd5e773bfebd3e1d78dc3d486a75b969e30f1dd0311d07c337440d275d0443
dist/2024-10-16/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=19989c6e9ce4d67e068d449b92dfedd8e07bd1a287cee0410f43aa43432346f9
dist/2024-10-16/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=c3d8ed4650b4f7902a8643bfee849926892aea2e664400b858f61000966042cd
dist/2024-10-16/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=6b0dce2bb77036d154d15ffb2495480ed8c8cc441dc8979b4fd767af80e0736d
dist/2024-10-16/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=de7b427a783d588a778a2301a1bf8e4fec076ede2006e275f45d82a87e965feb
dist/2024-10-16/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=43fdb72c7e74c86eedbb01631ec357c2cf469512c0c591d15f35f747bcfbbd30
dist/2024-10-16/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=3fccaaf7106f47302eb3c489dd722a91727e25351278a17f81d06fbb4cd4041d
dist/2024-10-16/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=988d6c342a4561790d1024455be643e17525ae07e02fe5238fc61d00c91d3cd6
dist/2024-10-16/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=71c10377a84b3bd612a83cd2822bc6c0eb4a540c681114d63be368da84ef3766
dist/2024-10-16/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=1e6a3c7080334663ef6fe246eae3482a05446b83c8a0c659084ca8186b9cab01
dist/2024-10-16/rustc-nightly-aarch64-apple-darwin.tar.gz=e68c96b5d6fc204944cd1bfd80e2c6a8332dedede98a968e170fa657e012ec1f
dist/2024-10-16/rustc-nightly-aarch64-apple-darwin.tar.xz=9f7138fecf991a17483e0359c7a5a0b4292cffeafdd4b52b7c1021cbf993ec5c
dist/2024-10-16/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=0f31c36e6b6b765e9814dd193861e2ae2a176160f22aaff6211a6da3efbc1fd0
dist/2024-10-16/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=ab4cbc70a6002bdba2955fbbdd99f03d3e54d14d32bd2f7250be6a323f39dfd9
dist/2024-10-16/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=e088594f42b88494401df68cc60b8d94a4c1199e3549aa6dffd513b0c5f7508a
dist/2024-10-16/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=a204d11814dfb6a3283ed84abf8b88492283eb6cfbec018a0f249d496e2db5f1
dist/2024-10-16/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=802ae62e1023c460739670a12b8a331637cec02aec14769bf0bbdbad44217555
dist/2024-10-16/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=9ab24e33a80a442a540720377855710c2b33617531daa625dff537d1251bb9b4
dist/2024-10-16/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=08a139d7e1ad8559d3add81416581984d24eb997f5d03f2ea85a76eac62df57e
dist/2024-10-16/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=dc9dface28b81a1b241a6ad034cd910221866cff7188d94929bd80e3d2dc1598
dist/2024-10-16/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=ecfb3225d805cb7faeb185e43471b35decc735c1330bcb45d54cbb93fac0db4f
dist/2024-10-16/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=60437f2b7cd51cebff36687bc904c7493ef834e39033c08e35883b3de03ed15f
dist/2024-10-16/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=aab495b49ad218fbaf6f36e0dc82ae76dd867ca77411568f15039e494154d890
dist/2024-10-16/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=51648f6d14e8684c3f258ede3e97371c1530be584b5bc47a92b7bce84d70b397
dist/2024-10-16/rustc-nightly-i686-pc-windows-gnu.tar.gz=6bf818c20105a30461336053b40b9b298388b341766536137a3fd6039e7885ad
dist/2024-10-16/rustc-nightly-i686-pc-windows-gnu.tar.xz=60346687b8359a3df7bc4d7beb5532be716bb699fe8aec76664b5b5b4d7cacfc
dist/2024-10-16/rustc-nightly-i686-pc-windows-msvc.tar.gz=48b542959792f1cb4c316ee417fec68ccab0ee76a68accbe667fc56ca9d5a367
dist/2024-10-16/rustc-nightly-i686-pc-windows-msvc.tar.xz=b83ebe192f8e2d82fdb0765952e69e4234f11fd6a0a4a69d089b2df42a3c637f
dist/2024-10-16/rustc-nightly-i686-unknown-linux-gnu.tar.gz=03b36beaf28462424b3b70e6a944d24a22a551c4fd9c245cfd5eef464047ec30
dist/2024-10-16/rustc-nightly-i686-unknown-linux-gnu.tar.xz=e00e81bfca624087f97ae2ff675adf08a72519240e31cfaf0f4da238d7be8050
dist/2024-10-16/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=f71e27157be06043624ebb769cffc92593d4db6d2a9edabec6815d0f9be64b9f
dist/2024-10-16/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=5bd77608b891be20b38739d2b1cd4319feeb13f92214e550a01c599349fd6ce2
dist/2024-10-16/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=0cda1b3a287843431991468cf8dea7a34221d42153e9421ed89a8f58d048e01b
dist/2024-10-16/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=57f3a4d73a40ffe0dad530334f2e584c1279ce3b81458023f034bf8c35dc6641
dist/2024-10-16/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=5d7c5164b12ad921f1d8461d0edeb17566bf4d5861d6b0f18f66ac1a91b7306d
dist/2024-10-16/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=8ba849b777182977ad9b87c002bff49ff9ad2007932abab98509e96274b9c7d9
dist/2024-10-16/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=03c12e5d01a6f0b66dfd728610fc0df2f3bef8d5cf418a4d5a385b11f35ecd81
dist/2024-10-16/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=db0b2d5a9a12c9c8aa0d5d3a320ef8f815ea2ac84718e1bbe94514e7480db6b5
dist/2024-10-16/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=2e3a85da6e7a74b079a5bbbbcd433e0271b89b873aec22c19537669bd908a98c
dist/2024-10-16/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=2b19af7ec21a9e442975b073455e4b3a2711832f6f4a521335034f47dd7725e3
dist/2024-10-16/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=c293489afe56e4ab984bab7c0ea8db292464b1b0a83b3efac3d38079f71303b2
dist/2024-10-16/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=fad8d9fce164461c81c5fca56c3557e76635f70ad755cfdb1a448faf161a6b02
dist/2024-10-16/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=1a4d7fb7e5d74649270e79fcdd5b7686bf3db6985d3a781ebb1f069404639884
dist/2024-10-16/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=cb1ca19ca8a99b68a1665937c2bfde2a275ff2746cd8b50e097202352a0f7cba
dist/2024-10-16/rustc-nightly-x86_64-apple-darwin.tar.gz=32d6c59ee1bb8d1449393b37ae9399d24ecbfcaa6dc5831ad2bdfb3a586c8ab9
dist/2024-10-16/rustc-nightly-x86_64-apple-darwin.tar.xz=5a9237c1b359da2c6aac0d6c9202f527d5982310477c414c3c03c6eee50feaf3
dist/2024-10-16/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=9b03ad10b3e5de01a813fd9be676135de072de0d3fe6db63e82ff881b9d81c51
dist/2024-10-16/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=1e7b91da95fa7fba74c4f8937fc9e02b592c4a66260aab1a4feca24e136501e3
dist/2024-10-16/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=59efe9285d460cf8080d3aaed31742cc7ae5dffebb9bdd3410be22a061fa8dc0
dist/2024-10-16/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=e64edab835454e2024081b9c447798075cc2df3703a8b627d9661c32233c8540
dist/2024-10-16/rustc-nightly-x86_64-unknown-freebsd.tar.gz=c1ceabe8ad4f89b401a72a6a02843a5f31267cb9762d1a8c30dbcb51c1967488
dist/2024-10-16/rustc-nightly-x86_64-unknown-freebsd.tar.xz=456708749343846153490593eebc55d78ae347d0a1096d0fdbea19c99aa24d9e
dist/2024-10-16/rustc-nightly-x86_64-unknown-illumos.tar.gz=e01be583da5371501755ca0f6d44cd2abef40543d7d97448933e27ba0de78c8e
dist/2024-10-16/rustc-nightly-x86_64-unknown-illumos.tar.xz=42dca4d9e7d76109a3c963b5783554d6ce0171001d744f3fa6b5001bc6ad66a1
dist/2024-10-16/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=4464cc28f6a15d5a2a1de098f28224848d0b91779bb70ace3106f3a6208d25dd
dist/2024-10-16/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=5f9b9cf42730255c27bef5187241736693b5e39de9fde935da25c9f33deb4325
dist/2024-10-16/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=d6c2b41d4fff28d12b254d3cdab480ac4a81054e50794b6cfb7ed30065cad5a1
dist/2024-10-16/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=1acfe2f78ff7aa747e5b307b40ff5a8be5e8076897b78b2fb5828d1bb1d74cf1
dist/2024-10-16/rustc-nightly-x86_64-unknown-netbsd.tar.gz=9d5bfab5bfb9e6d627a5acd1f54fb164538e84c449aa3ea15841636257ec7ab4
dist/2024-10-16/rustc-nightly-x86_64-unknown-netbsd.tar.xz=dddd1663a821d99ea19864435e1c7daed6bcb4fd914e6b79c94d644836bc8d1a
dist/2024-11-27/rustc-beta-aarch64-apple-darwin.tar.gz=58e2ba5f6a388a5bc9ecfa1c7ec4ba3efd9662e1875ea5fba484c75c5f930227
dist/2024-11-27/rustc-beta-aarch64-apple-darwin.tar.xz=95f3ed14a6e3093cdee83f80227c7966783fffcc0ff0be6ef095df0dc744b9f8
dist/2024-11-27/rustc-beta-aarch64-pc-windows-msvc.tar.gz=687b58e25baa685be9357048cc1e0c469c25dc6530db55e0179234615ff4d289
dist/2024-11-27/rustc-beta-aarch64-pc-windows-msvc.tar.xz=694e2405efb25c53575599ad6573d8c4646a168e5d4bde922ef5e7d43f3e530c
dist/2024-11-27/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=4b42d00e701f90c1fff9a692f1bc1da957fcadbd1813c3066dc1f1990bceadcc
dist/2024-11-27/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=4f83a8cced878c03aea2d6cec7e1d588c2b6590850664f28f3b49a3be3a8b827
dist/2024-11-27/rustc-beta-aarch64-unknown-linux-musl.tar.gz=bae97ca3778fbaa40f6db4da4f6da0b2bb870e9880165fc3126363f55a1fb23a
dist/2024-11-27/rustc-beta-aarch64-unknown-linux-musl.tar.xz=3e617e866a8c03fef243dede8c086d085a6564aeeb5570bada62db5a16e95f2a
dist/2024-11-27/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=96d2f23814db8286de9ffce7bab033aa4dc656f83aa39418c8f877a5befbb100
dist/2024-11-27/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=0433a866c4d8a434990746216232759345d3ef556b0b92358b231fc1e727962e
dist/2024-11-27/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=6a776c6eb2b7b4992eed6a127d11b8845695cdc5d23938ced2267f88f8d97033
dist/2024-11-27/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=2649e0f522755dcd511a6459258c3c3a24808fc49d3513f3d9098b17bd0f2c79
dist/2024-11-27/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=02a65e970ee930b46c2d10e1eb3d2e6f2420e08bbef039f10a8311baf57f274f
dist/2024-11-27/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=3843610c7ecf98948a5f78a364c223d520a084bc8c49ec0c3c8ec48bad6c0bf8
dist/2024-11-27/rustc-beta-i686-pc-windows-gnu.tar.gz=75288ca1e65157b8902195ec2fff31015017c90d3b8f51890f2f851529b200cb
dist/2024-11-27/rustc-beta-i686-pc-windows-gnu.tar.xz=5c694e50b41cd6f2c7b59b891eda3e728a1a2c56617b96c9da001b35885637b4
dist/2024-11-27/rustc-beta-i686-pc-windows-msvc.tar.gz=6d1a66c090322ccf272a425c779f9165398e6bd9e0c7e5d0a5f262086d43ed88
dist/2024-11-27/rustc-beta-i686-pc-windows-msvc.tar.xz=e826fe8be287f8969d11f620da9d01ea0d913eba145fb79ae86bc78674f1b919
dist/2024-11-27/rustc-beta-i686-unknown-linux-gnu.tar.gz=31e0d9a1ff97d92c391cc913fd865a0c8afd614279654350d469bdf881a1b1a3
dist/2024-11-27/rustc-beta-i686-unknown-linux-gnu.tar.xz=3b11a6be4863cb6ad420b66558b7745431834d1fac5dbda899a384dc30b526cf
dist/2024-11-27/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=59d96cd092a56d12ea796b65225479803edadbdcb483effdfa36e191f73483f1
dist/2024-11-27/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=0714a469cbd7d96118e9260f80fedf34b21234776904e9c8ec5b71c9493dd36a
dist/2024-11-27/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=25113ca9719a036ae581f68df4dda74f1446b49ababe7bb194510fbd1b296e7a
dist/2024-11-27/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=25bd910ea722fe2d4a1e66089352c92f97759ec7212af2b9a04431b469ed8e12
dist/2024-11-27/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=7a83c9f63d88849c4d691ad1d7fbe7ab5924b5a7d76378ddff5024269be95310
dist/2024-11-27/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=fbbb11b4c986186d94b0e00ebc70400d0071efc2ba3b802abdd877d86b8cacdd
dist/2024-11-27/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=6223dff24490e3e8506dfbe2b12620155d7c05fce92191cb01f3b28e269bf1be
dist/2024-11-27/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=6fb1edea73bcb76d9cb6061d1aba15ee4655a212c1bf96328a225c7c05df3462
dist/2024-11-27/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=0b7bc9ec0c40a6203fb62eb71fb6eeab43a4f64a2f7d0d51a1e0d041a216adb1
dist/2024-11-27/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=d77a49acbf26b8c9a2a5f79fdc640feb1c81b9fa38f442b81f69127f49c7cde7
dist/2024-11-27/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=bdf45a37fad10df4822690ea73840b38ee3e1048878982e625efbad3b2054f28
dist/2024-11-27/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=ad6a2f03b2e27711e1ec4eb75502782c4bc0200cfaca2b5246e0bd5b86bf29ad
dist/2024-11-27/rustc-beta-s390x-unknown-linux-gnu.tar.gz=b0cc3024a717d33775dbea63e83f317f8826e564ceb4ecb7a6cf23676f66ccdc
dist/2024-11-27/rustc-beta-s390x-unknown-linux-gnu.tar.xz=9d5b44a82803d5de5355ffced6ec1dcb9860950910bba6dc54878ad4da7ff444
dist/2024-11-27/rustc-beta-x86_64-apple-darwin.tar.gz=c7174c35b530453182f5f0b15c6684c030a2ff2770f4cc1a4a4ba75695e53b99
dist/2024-11-27/rustc-beta-x86_64-apple-darwin.tar.xz=c68c26159a3fb4d4380fb25488aa78223989893d7786b8ec947d82ce0cc905bc
dist/2024-11-27/rustc-beta-x86_64-pc-windows-gnu.tar.gz=c97caf7877097d78fe2191e715e3a45d827d28c27b4dabf0747f8ca522ee43f5
dist/2024-11-27/rustc-beta-x86_64-pc-windows-gnu.tar.xz=b7794ecabc42698cb77c1c90d66676a8b1b3632108ab95954ee496ee7d6e5708
dist/2024-11-27/rustc-beta-x86_64-pc-windows-msvc.tar.gz=28068a6e050abe21933920dba3ead2261f7d0c09687d5a86a5db51cca6e72ea9
dist/2024-11-27/rustc-beta-x86_64-pc-windows-msvc.tar.xz=3860d7ec8564019c79551727a3a54c66453a7d654fbb89b8feeae75d9021fa77
dist/2024-11-27/rustc-beta-x86_64-unknown-freebsd.tar.gz=6c2a918f8d40ba01e648565c98ea120d32562dd93820e8f2e33abb2aef08e1da
dist/2024-11-27/rustc-beta-x86_64-unknown-freebsd.tar.xz=5d1edcc6c4be49849c3c2d1c3c173d4a127db3cfb615093e5ee396e0d0c77366
dist/2024-11-27/rustc-beta-x86_64-unknown-illumos.tar.gz=a64c30d82dca58d09bfa38e72bbe1457b48b101157193a3ee33dd85922bbfe9d
dist/2024-11-27/rustc-beta-x86_64-unknown-illumos.tar.xz=87d14b146386fe1f9e24fedc25e1bf9682913bbd7537047b0baef0d74cad5473
dist/2024-11-27/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=3f186913535ac59446e249f4d3e35e3d93a3f8207b31ee31b3f70af8344856bc
dist/2024-11-27/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=0c17a60ebac74a9cdfc2ec69fd71a21e370ff178f4c83be6020642b55b6d78ab
dist/2024-11-27/rustc-beta-x86_64-unknown-linux-musl.tar.gz=327973698dd0ffe9b2d56b3b5929f82ec552f2002b4113fc9a738e27b0005ac0
dist/2024-11-27/rustc-beta-x86_64-unknown-linux-musl.tar.xz=d7e2f768922ae36a9eb302667398ee308c13f829c03235682529fce90253813d
dist/2024-11-27/rustc-beta-x86_64-unknown-netbsd.tar.gz=13f327974170a0423ea6e7241cd3a454ab8c39b657a707c08f2e306a7a657b45
dist/2024-11-27/rustc-beta-x86_64-unknown-netbsd.tar.xz=5c75388802c0ddcfa51336883f4039b6f7963e0efbe47c209bb455c12951990b
dist/2024-11-27/rust-std-beta-aarch64-apple-darwin.tar.gz=84c4c02fdecc669c5d26c49120fdece5899133c098f5ef791ea19aba33936dea
dist/2024-11-27/rust-std-beta-aarch64-apple-darwin.tar.xz=7ea047840073e6ad3123a61ca799bc56c951edbb71cb8495ecbc2029759a0190
dist/2024-11-27/rust-std-beta-aarch64-apple-ios.tar.gz=dfb8207b4b3bc13a9704fd1d212d92a22a0e7a57293f24f28bcaa846ad4c08b6
dist/2024-11-27/rust-std-beta-aarch64-apple-ios.tar.xz=96940a84d95b4cfdde84a501758c9dd83f5d6cb5afce9142917d5cb3dd75c040
dist/2024-11-27/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=4ed66daf59e9a8b61d66caef4b2248be72049282518d7526be771301bee2b905
dist/2024-11-27/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=013d59e32097917b269c45a837bff380a41c4f6401b0c145264cca5a1bbd91c3
dist/2024-11-27/rust-std-beta-aarch64-apple-ios-sim.tar.gz=270a0322dd3c2342745faa8797f4f64da8c0028b322385d209ff65cf04965a47
dist/2024-11-27/rust-std-beta-aarch64-apple-ios-sim.tar.xz=9d54f7f51c99f17ba9cfe7cbe005ddbfe598f8af6df1dfccc9ef37029cc08b41
dist/2024-11-27/rust-std-beta-aarch64-linux-android.tar.gz=9ae4c1d6044b2c3586791f127108e308e0a381e8e14ecc20b3830ae5258a03c2
dist/2024-11-27/rust-std-beta-aarch64-linux-android.tar.xz=689225ea098a88a88e8e2269ef53f964405a6c31b3ee2bda0fef98da4ed9178e
dist/2024-11-27/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=f1d9c996cbe468ca93b15c76b84c544930d7452f1eff2968a298c885203f14cb
dist/2024-11-27/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=f3f8c088d74c81b2457ddff57008cb908cc86e16d0fac60d10969e45210d88d6
dist/2024-11-27/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=fb4e5d66911a47bd63429686885cd5c7f0a6310b25622f36bb43a754300526be
dist/2024-11-27/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=ab6c7d346bfd72f06fbbc198743bda35fcb7fd1e131c05c54935b6ceff282f17
dist/2024-11-27/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=32b2e0d5161f7d8354d846c91e5cb25530e78351dfcff4ebf0a6fba669e2c483
dist/2024-11-27/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=656fc4a8af570b28b3f83cd59d4e5226f15d11b5d8c26b58ca2c1b2a4e18c4df
dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=13c98efcde78c1e187f728509f2950a0a407ba32e730877cb9ca4cbb4ba01469
dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=6372891715046375fd0a04e80c95bf79080db2d136e187b02ea96647e9281407
dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=db156e0d5db6f04621e625e92323a04091c049a8b5e2b4f7e0fb2e50b81ab2ec
dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=b610214bb59b8f58be96b84b0f13e5f50473e21039f6e827fa16c446d0e9ccba
dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=99f96b0bda31bf21853c96b3618408587f275f46ea9bd7d1fc741e58343a5625
dist/2024-11-27/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=dfa1f209f546b457aa6ef742a645f00f55c70fde86522c737f7a560494170157
dist/2024-11-27/rust-std-beta-aarch64-unknown-none.tar.gz=4735b29991a2337a7e2016c5a827635e17ac149372efafc0442a86b0dc0759fb
dist/2024-11-27/rust-std-beta-aarch64-unknown-none.tar.xz=fead0635c572aa4f5e5564e497f1b7e892217ebe52fea54aedacbefb32f6343d
dist/2024-11-27/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=bbb9b6fedb874a61d99d22b4cdb2d20d8b9e6c69924922312692aa526851b960
dist/2024-11-27/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=9e0d48236676dc9947565daf0c2605316c5b4abc06bdb1c343559c46b9c4e304
dist/2024-11-27/rust-std-beta-aarch64-unknown-uefi.tar.gz=e230ffa3d46dbe5330416cdf8b7235b8dc2cf119ef8990b422eeebd017ebd17f
dist/2024-11-27/rust-std-beta-aarch64-unknown-uefi.tar.xz=38a5560575740f92cb8664d204924cf7a2972e0f2f396852d8a22befd2cdd848
dist/2024-11-27/rust-std-beta-arm-linux-androideabi.tar.gz=0b0a9f95d10484207c52fcd8ab1bd56903b53f18ce46fe263d5b7bb085044246
dist/2024-11-27/rust-std-beta-arm-linux-androideabi.tar.xz=91f7655ab2bce397a0821edc0f523dbf2bac0af39a50ead106eb1de637ec5c44
dist/2024-11-27/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=e8210f03bc18661954f147dedd0b4af721d005866c0c4fea1e91594cd6c9bc2b
dist/2024-11-27/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=56a623817e6a600e802727d59d4cd653e84cb628695e39ecb23ae99065113115
dist/2024-11-27/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=310a408bde58335d8011af480d4f8c38745865772d71631596cef1a79f9f4fc2
dist/2024-11-27/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=fd6766ea9e828adc2e43ff1654a459785eed05ad00c7f6804c742ff8ae8f6b8a
dist/2024-11-27/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=e663e30526d85d89f41456a3d5bcd411397cb69e7cb9508aa1472b015963fd18
dist/2024-11-27/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=0361504ada464a7d21e7ac66fdf9e1e820695f3a8ca4854695e78a748c5c7a18
dist/2024-11-27/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=c375be97e626900d809390c61bf6f2d689c9fca8e58c85e4e02b694bed4c5ce0
dist/2024-11-27/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=c33e3b4f9098860f75fcc9a8f86c7e7173692ad4c19cbb2c0de068961f87c192
dist/2024-11-27/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=3f50d9afd9df4db85958e4575429dd4c80b6702a8d91c3f1d9327345aaadefe0
dist/2024-11-27/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=0016d3a6ec8351ee9fac2eeae358a0854a3c2b360822bb3ba670255e8f27f57e
dist/2024-11-27/rust-std-beta-armebv7r-none-eabi.tar.gz=f23117b972ccd21c0a6f4db4b544401045c9f157595a297fb56d7e864cf190fe
dist/2024-11-27/rust-std-beta-armebv7r-none-eabi.tar.xz=ab9be4bb25b1575af276cbec7fb1a1f8c683741b0f137bca7b4b61ab13575645
dist/2024-11-27/rust-std-beta-armebv7r-none-eabihf.tar.gz=673561456e26bc992cb6a888c34c0b6b13e1bd0d3e0764360a785a6c3369f0d0
dist/2024-11-27/rust-std-beta-armebv7r-none-eabihf.tar.xz=29c6f01c636bcd901b88e92c60874c454369efd41f690d74b1fa2adf3450166a
dist/2024-11-27/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=c214d4439676a19c057324dc736d63aa0328ac74c0eb9ced8d782d8bc89757ae
dist/2024-11-27/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=4baf85ac632750c35d007bcae8f23720208c5197f4a1d49b0a85b2b0e137f603
dist/2024-11-27/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=a7e81c0e80f2508c81ba9d8e658dabeb19af2de6f7365f6e377d39e99d8449e7
dist/2024-11-27/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=3f37f746aaa03107573a3a2b201c15bf86777ec405dc03640e7d3f24f718f67f
dist/2024-11-27/rust-std-beta-armv7-linux-androideabi.tar.gz=fe7c7ecb8a8e612caf0e7ecf04d18ccaed31d8b93911ded6b3cba0c78fcbbddc
dist/2024-11-27/rust-std-beta-armv7-linux-androideabi.tar.xz=d571b714821de4b7d2accad221b5e043e7f9aead8dbc06586f4f7ff3f3f3e38e
dist/2024-11-27/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=663396f0e4c45bfc041b1a502b64627620f499ca6343664633761c3fb1c2229e
dist/2024-11-27/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=4d8c47d74958e3b1058ab721e9c6635774afad0252f251b0c9fe4f0895d0c81e
dist/2024-11-27/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=3cba82809bc1204b6e8f62877c5e9f9a08f111da7d439032cc30d55be0e88fd7
dist/2024-11-27/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=d525a4dde496e72fd18c6f2a525756d652ced436007f513267e9201d8b1c0a40
dist/2024-11-27/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=ec0311a0722f205b117160817b2137e9a73f0f4e540930d61c831ceba1265f0d
dist/2024-11-27/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=c63c4a28225dfca26baab129f06d8537fae5710083046f203a2fb73c50b48671
dist/2024-11-27/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=52eae1bdf37366bf406cff95e5e7979d0651979ae5ad4c036e8badddc8ec8b82
dist/2024-11-27/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=542791fb5cd80fe5515ab0812c9fd8671f083151d4262fc76d26f7723ba961e1
dist/2024-11-27/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=91697f75c762bdb51f19348953768a45bc37c389c2e904a56f4f092604ed2d1c
dist/2024-11-27/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=a79a7a5974b365f70598c413da3db8262d14414e3b4d48dde45f529bca4c6ef8
dist/2024-11-27/rust-std-beta-armv7a-none-eabi.tar.gz=6eec497ec2aaf6c5beb8e6dfbeaf32190b6f7206aebffb7499b5fdd7e5e7643a
dist/2024-11-27/rust-std-beta-armv7a-none-eabi.tar.xz=234924a6746fed2efa112b0b805d0ca56252b6cde82e6422774871e9c009fed6
dist/2024-11-27/rust-std-beta-armv7r-none-eabi.tar.gz=1b0cd107412fae22266267bd8eccd2b39a36afa8936da3888d0bd0d2f4cfdb1c
dist/2024-11-27/rust-std-beta-armv7r-none-eabi.tar.xz=0d0d1ee48f9032df88ea7b3f73f06300686f4d5b9fc16f1d4554caf8356cfd74
dist/2024-11-27/rust-std-beta-armv7r-none-eabihf.tar.gz=72f0549de44925bd08286e092261164dac47826124123e3fe707411a3dfa756c
dist/2024-11-27/rust-std-beta-armv7r-none-eabihf.tar.xz=eb45acd55dd70be3670de83c8cbef5b6ef05827b3f97b7c71679a19c88f8f3e6
dist/2024-11-27/rust-std-beta-i586-pc-windows-msvc.tar.gz=edd8dadbba618f2a786dfcc68e4a5c7f2b7cf1528d1c16ca6ddbc52622df95c6
dist/2024-11-27/rust-std-beta-i586-pc-windows-msvc.tar.xz=ae59c5d77b31aeac30c22104abc0abda6b7f725419e9f86db6cae634ededf262
dist/2024-11-27/rust-std-beta-i586-unknown-linux-gnu.tar.gz=8996c94269e4c60270d253ea75bddb9482facc441ee2314a387888924bea1d92
dist/2024-11-27/rust-std-beta-i586-unknown-linux-gnu.tar.xz=f6b59e3d6e7f0e458c048ad4aad9a2da23f3b54aeac20a905d2e00379da1bd6a
dist/2024-11-27/rust-std-beta-i586-unknown-linux-musl.tar.gz=85f22b148be72691214dee620eac582405dc3b8937d2ef7c480c9070b963af3a
dist/2024-11-27/rust-std-beta-i586-unknown-linux-musl.tar.xz=4b48538541dd20fad8569cb3f0994d5ce6aceaacdd8b319d00b0234cefc5c267
dist/2024-11-27/rust-std-beta-i686-linux-android.tar.gz=6e5ce19fc4cd8cf4dbaca8b31f4032b08ee413ce20f354186e4945efd4e8b6af
dist/2024-11-27/rust-std-beta-i686-linux-android.tar.xz=5e78b98abdf2b7348381863052c109beec025a5f68285ce72e6f6e9245c22ce3
dist/2024-11-27/rust-std-beta-i686-pc-windows-gnu.tar.gz=50057f990d1127e7d693b1c5b9539b19262a478130bed51dbc2837d61d2db6da
dist/2024-11-27/rust-std-beta-i686-pc-windows-gnu.tar.xz=ea524b276e42a1cb918625df12b8d3397ada5ecd43bb9ad5c676747e1f916c8b
dist/2024-11-27/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=c7c9093e277187590b86ea02fcd940071c8bce93a894396d73953276ec58eb1d
dist/2024-11-27/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=a67879ff0dcc591d30a155fd972149953eaac3b139bec9aca3a383dc277ddbc6
dist/2024-11-27/rust-std-beta-i686-pc-windows-msvc.tar.gz=a086c8272f9c7c0db3d5de37b027478dfc22fc577c613254a821700c645df3c9
dist/2024-11-27/rust-std-beta-i686-pc-windows-msvc.tar.xz=8ac4b938e0b643e47d6d0ba6e5283887fcc73cb1a825fc065c35879b085d9c28
dist/2024-11-27/rust-std-beta-i686-unknown-freebsd.tar.gz=3614b95b54ca24c598e3ed6e14aaa86f7048c2a5be2b3e9f97d9ca00f3d890ce
dist/2024-11-27/rust-std-beta-i686-unknown-freebsd.tar.xz=6d36127f5c113b01300fa0d54062bc1137b51d2514346c8d84bafb9f2c56a972
dist/2024-11-27/rust-std-beta-i686-unknown-linux-gnu.tar.gz=a6d33a96eeb667f3f4649ea6ccdd6212a183bce85f095ff7db5036c3a50d35a6
dist/2024-11-27/rust-std-beta-i686-unknown-linux-gnu.tar.xz=bab1dada484d61bb96e2834da5fc6ed5d4d788e6636849e9802f9fb6bff45d55
dist/2024-11-27/rust-std-beta-i686-unknown-linux-musl.tar.gz=0ac331a1c9e384430a5f316809bffdf01bae3ae9cc1f807f07142ffde7388602
dist/2024-11-27/rust-std-beta-i686-unknown-linux-musl.tar.xz=136341bbf4c820dfc98e96cee41fa0e9fcbc7d81d2772407efaf1d4be6d10f7f
dist/2024-11-27/rust-std-beta-i686-unknown-uefi.tar.gz=32f06ca3b2752a8687e2f282a59823671fcec672bffc0775a9fb27da50b6bb11
dist/2024-11-27/rust-std-beta-i686-unknown-uefi.tar.xz=b2f376089b39a34f3308833ce9bf65200f9665e5c55bbda3e5b7e9c5096b7e67
dist/2024-11-27/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=a2ca950893c93be71c7db707230b98674a29c013546e27d95bdf8c3c6eebf9a7
dist/2024-11-27/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=c70b58f4583578347e9f0fa20d17bd5fc51d88717095e05d73091209f2a363be
dist/2024-11-27/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=ed284c40b6253c022e39718dc2af2e4100ca7e805d35d86aca04937586f26ece
dist/2024-11-27/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=3efcabf46e0d02505ebf0926c6c14e0c70838f9b510f2328ccd98dd0fa977794
dist/2024-11-27/rust-std-beta-loongarch64-unknown-none.tar.gz=9b9f8418fdf64fef652f15b28a1a1f2f8c63c18da8b323994f10f921010721ab
dist/2024-11-27/rust-std-beta-loongarch64-unknown-none.tar.xz=fdc673e4b250424c6dafc18a165ffb592aecd7b897e483af8ca54aa145a0e6a9
dist/2024-11-27/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=802d22c1c364a58402f9313c6ba2f58b79f3cf3163842a608b78680fa2b3d476
dist/2024-11-27/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=dc4932d91d8a2887d309dbd6317d6c41afd083043f44742138ca7c97f60b931c
dist/2024-11-27/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=636b19ca036fc7ddcf358062c98f6bcf31e8c2cd035cbb9dc0a6b96c81217f7c
dist/2024-11-27/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=31f80fc50be95bf665d21fe52b714532ff34ebfcdc0c975bb68f7d2f2cebd0e0
dist/2024-11-27/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=f2c83275df652bc5b387525e77a1aa30bac31fb301b304ddd7e6bf402e140c34
dist/2024-11-27/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=41358bdb20fe3a97a95fd7b656b1ed03d5b8012354d8cfad2437bc9ef6c7aeb6
dist/2024-11-27/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=49b8f286b4abb3b34bd38c92ea3e15efbd1f623d5efa7bcff10711b595363579
dist/2024-11-27/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=283f065701c77fa47a2d5413d20fa40989fbbcc75bc938889de6c4f9b6b9e53e
dist/2024-11-27/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=d0ee5ba5dd6f94dc6ca981be0d55f2e3f51c2af25877131a7a74e0ab9848dc3d
dist/2024-11-27/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=79c78bb31022ec8e7a3fad9823c5d22ac553d389104844110473d1877d8c8302
dist/2024-11-27/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=b953686e3034f2b51033a2630328c8eb5f59fdf8ef4e26189bddb8efb4c482cf
dist/2024-11-27/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=fb25ac2e68594d379f915f0555b3ded2b1a7b5a67144e12eb62949f540b0d957
dist/2024-11-27/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=fbf5a16a57de3a7e846389aebe18bc7871f43e67eff39fc9b4744b5a445b2639
dist/2024-11-27/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=55a92aa5770924a21b706724c15f58d66ef2ca5b630f7025f6ba1416152ef350
dist/2024-11-27/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=b880b7209ea604761ad2a46832925d32fc547737b879645fd3cf99ec235e7b39
dist/2024-11-27/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=c48cc6a6fda06fab014c0b8fef49006dd32fb71f8e981ba44a0c25d47fbfe034
dist/2024-11-27/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=7d133b6c8d0e8b8ec8b65a74ed8d64a22e2fa5e4f6d4a1e36f9e0ebb8826f40e
dist/2024-11-27/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=1c507e003c38115bfffe8701df1ff7aed6ad16ef5ac4b383f84bd2d6aa0216bd
dist/2024-11-27/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=111a909b3d1a04b328ca1c1f247ee4eaaa84349eeaa8df77f7901bbc0efc94c1
dist/2024-11-27/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=d29f92ed071c60259feaa8005eb5392da549f8e2069fecb1b77e112f89cf1bbc
dist/2024-11-27/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=241b1ec9ef6a89277944c9d8021f521284dc28822c5f80513b6cd94d2bdd1d64
dist/2024-11-27/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=9f5b02be846fa2084becc5616f024094d47beca102442ac7a0e3588e0f12ee7e
dist/2024-11-27/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=7272eae1625415c0f57bf541dd62c14e02b9946ca1de04615827a1f5218c2181
dist/2024-11-27/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=d4bcd0068d3c9e7351565fec57ca68d36c9ddbfe59249a6bd2c56930ebad2257
dist/2024-11-27/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=758ccc47004398add2e3cfef52e4839e14dc4d132a215658e576e590401a28ca
dist/2024-11-27/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=6902fee1027b0136f8dc5179e69e24ed9e34366e9409129b9ba223043ddadea1
dist/2024-11-27/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=3024570f3e382a57fce0e832c52d080a83d42206d8412b724361bd1f0087ec4d
dist/2024-11-27/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=20eaa72b6fa32b9884b43030a0bee554bafa9de3f3b51c5768ba0ff47ec492c1
dist/2024-11-27/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=a3eae70be3fa5b0a56cc88cc6433cdb7c42b3b974caf0d879d21a5219f4f826e
dist/2024-11-27/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=1da88d1882d4dd1f15ca97e016f392a01b56951882ae75929023e83fa557d796
dist/2024-11-27/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=387cc8ccaeed6f9c6a8c9d21004e45ac97a9739643a63448eb893e13ed4df22d
dist/2024-11-27/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=1b9afe3631fb7847b2a8a8f483fc00ca203ccc18ae298339801dab1c7b06b3b3
dist/2024-11-27/rust-std-beta-sparcv9-sun-solaris.tar.gz=f9a4d2115d6fce06e0da7a9f579b197d383034c218573e145b3c7dae0aad21d4
dist/2024-11-27/rust-std-beta-sparcv9-sun-solaris.tar.xz=c352bc631e538d4e68eaaccdfb9dca1c9dc8ff0ef4a75d8ee91016aada39d717
dist/2024-11-27/rust-std-beta-thumbv6m-none-eabi.tar.gz=d97851ca9193d98192a55aeaf695973ac706e6ba3e198643c200cf410817b424
dist/2024-11-27/rust-std-beta-thumbv6m-none-eabi.tar.xz=89a6524a3743e5a769a583b4a6bf8a76ef5b45c67b7e39da7ae24b687bed4943
dist/2024-11-27/rust-std-beta-thumbv7em-none-eabi.tar.gz=6fe614db166618a8f2ccb5807e02884daa8bd8dfded2164f88d79fc688047020
dist/2024-11-27/rust-std-beta-thumbv7em-none-eabi.tar.xz=91c5e4f4575ab004119797988679077e5057881ad9a7f6790b673dd062a8b7ee
dist/2024-11-27/rust-std-beta-thumbv7em-none-eabihf.tar.gz=d0e05467fb1562ed7d6687a50b7fafa14ba0c2aad328f0e7c19eaca1ee366475
dist/2024-11-27/rust-std-beta-thumbv7em-none-eabihf.tar.xz=0473372df5fece49e58efcd3b2a702bb93e47ec149b38fd5244ad667804e7c63
dist/2024-11-27/rust-std-beta-thumbv7m-none-eabi.tar.gz=e6b6130a1a571325cc1bda8ddba6b2672104c2feeed5c93c6022bfcc8ba4b247
dist/2024-11-27/rust-std-beta-thumbv7m-none-eabi.tar.xz=d4c739c42104e04aba55b96a3ad434e11b013ba44649dd3a648cfbb15de83eb9
dist/2024-11-27/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=e427d5d6a53abfb53b436df96457d58eedc648198fce6b1d976b50de18cbc31a
dist/2024-11-27/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=11142018c11849c21adaa7096abf50d0c923f3b8f07d67eb96d6860d428e9b27
dist/2024-11-27/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=46596d8f2271dd5a6f0f84387ac19d0e81976adfc6050b6aab6cc554102fe469
dist/2024-11-27/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=f3d0c9db1c50a018540278433fed2e0ae4bc798aa0dac87cf0f55ad1808618a1
dist/2024-11-27/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=c46fc4bf174fc54f5565fa04e80efff4e853642e3e5f0bf5b696a2bd6e7ae817
dist/2024-11-27/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=706c10ef22cc16b3d4cab8fc09d8783384313b9f774229470b8ae1dd292850b2
dist/2024-11-27/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=b9cec80ed374f7b5f22f1446e3f2e0dacfaa0e2d4d6c631ad66cc42a23e156f7
dist/2024-11-27/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=41c67ee95e72a3d10bdf739c4841bd937c4e0b19c33451724c1f603b4bd2a318
dist/2024-11-27/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=5ad8603f98cff0d5d015c72f3a55730d75d59680a867c067928bf4586c00d805
dist/2024-11-27/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=61a75701f7e000f86f318a04dc6746f029fb933e0ea94944d76c7eefca1f24b2
dist/2024-11-27/rust-std-beta-wasm32-unknown-emscripten.tar.gz=89bfbfea23974ed75a53ff134386992e9c257d3e51a55eb49847aec9c5ba6b13
dist/2024-11-27/rust-std-beta-wasm32-unknown-emscripten.tar.xz=e34d1586bc6767b4b244f98754badda706645fdec7168ddc0a409b9f95f2b18d
dist/2024-11-27/rust-std-beta-wasm32-unknown-unknown.tar.gz=8a88bb923e138d0015c8f46bc1c3d5f2f5f75f40dddfca72a49eed42c080d1db
dist/2024-11-27/rust-std-beta-wasm32-unknown-unknown.tar.xz=79a980f2b999c3e3b04d7e327bd2b548007039b45da705847c6da2bfec3ffc04
dist/2024-11-27/rust-std-beta-wasm32-wasip1.tar.gz=454e2c4b46b4684e591c6e4c0f1ce8e3c44623a29d561be3a481ae008072dbd5
dist/2024-11-27/rust-std-beta-wasm32-wasip1.tar.xz=4dcf652ab51fe03c4691de46365218dc483cf1f7c2f5a552a38509685a0ca873
dist/2024-11-27/rust-std-beta-wasm32-wasip1-threads.tar.gz=c2c34d9b3998633cfa145dc2a5568a99d1fe26b91c5be55a08870a1d27db4af7
dist/2024-11-27/rust-std-beta-wasm32-wasip1-threads.tar.xz=4d5b25e4b5fb71d879f15f320f7513eec1ad078d3ca6f525ebf56b9620bdb5ad
dist/2024-11-27/rust-std-beta-wasm32-wasip2.tar.gz=e1385a340d3d9a4003cc456156bfbb1435a5255b2bdae3a40b6d7339768bdc81
dist/2024-11-27/rust-std-beta-wasm32-wasip2.tar.xz=245e7914174d213ddbb550b09fff200f419bcd632de98548a470013891666410
dist/2024-11-27/rust-std-beta-wasm32v1-none.tar.gz=d5d924ea001f914bf87df8765b013db6e838a930a4865e95f8d35bfaa86bc81e
dist/2024-11-27/rust-std-beta-wasm32v1-none.tar.xz=bb98d0d55f38f2308bf99d4e5f11842683452571075eefa5b4e1f18f2bd553bf
dist/2024-11-27/rust-std-beta-x86_64-apple-darwin.tar.gz=edd5e7ea230a13be750dd74c5f7a7dee20db8683f7978aeb352307a0ce110b9d
dist/2024-11-27/rust-std-beta-x86_64-apple-darwin.tar.xz=c6cec9a501d9873e3c7abdefd5b9418f7250c8cb915be8b816cb48dedf1f201e
dist/2024-11-27/rust-std-beta-x86_64-apple-ios.tar.gz=e970c2a4ebfb69219dc66e4c7541cf22c52da5f94983c7c914df1f93beda3d31
dist/2024-11-27/rust-std-beta-x86_64-apple-ios.tar.xz=594ae9bf5f1501322d986dc91249a48a61c22371513b872fd63e134097ac55ca
dist/2024-11-27/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=d57bf579b4629417dbe1c02506db4a4ba4428871a2684141d21303e6c99551f5
dist/2024-11-27/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=714db83e7563a5f286fb37bc629b64834a9ed981bb9a05931122072f95e39bf8
dist/2024-11-27/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=feafcba9c46ba3e5fa0bd9b5bedc05ef3423c9962dc4d25a7b2367e3e1caa679
dist/2024-11-27/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=78fbc8f45df64dca21da7223b5d081111922f2268fcc4f1f83595d159d310bce
dist/2024-11-27/rust-std-beta-x86_64-linux-android.tar.gz=74fb57da7f2907afbaa2a7a73847273ef81e2d6902a326f1ae87767677a864d3
dist/2024-11-27/rust-std-beta-x86_64-linux-android.tar.xz=3216eb73d9c9effcd2a2de7f63d78055c3d7e50fb8141e2910a45a36ce744ffb
dist/2024-11-27/rust-std-beta-x86_64-pc-solaris.tar.gz=3df431c8941ac28906c3a6568d3debe478d9349d868ea8bd3ad79e65792c20e8
dist/2024-11-27/rust-std-beta-x86_64-pc-solaris.tar.xz=548c2a6104148bf0da21bf5e009b80522fd15539077a62021a64f16282815a5e
dist/2024-11-27/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=235228431d67feb4c8e6aad44e20bf68574f335e8f948808b597ae98d827171d
dist/2024-11-27/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=5a2d4ed70aed26f902cf45e1dcabc5f25884cf6e9aaff775405ba9c1f0a5cacd
dist/2024-11-27/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=818131158e8be6af4b762750f7927c4a799346c94059a6073230da79b4408720
dist/2024-11-27/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=fc08b39833e2c9319dcb55cef5c6d1f0110aea794c9a6f163ca39749a22a94b9
dist/2024-11-27/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=6164c3ade38c03113193301b815c52df0ee84a4ca1c8ef21e1a56d386e28df00
dist/2024-11-27/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=0846126e6c4cf2b5184979b6025fbb7bddb5c22905bc7ba31fff69f6b1459280
dist/2024-11-27/rust-std-beta-x86_64-unknown-freebsd.tar.gz=ae308e29be13a176b26c142347a81facf8c11ef1a28e67d5898f4f2a0d3344ca
dist/2024-11-27/rust-std-beta-x86_64-unknown-freebsd.tar.xz=e80bcba8b011a4dd3f7b2a2cea69b5a95ae2cde9b2d9078ac8fdd492ac162139
dist/2024-11-27/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=b25f0d605b7f4a2a93adb746e32f59bfc26af569a4169e9fb203cb33751d1575
dist/2024-11-27/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=010f35236062a651b1b54d7c928068efca8dc486856b84b04e98f4f97583bf32
dist/2024-11-27/rust-std-beta-x86_64-unknown-illumos.tar.gz=db3d258c2caea73b469feb9c11fbd3bcc29d22c3969c406321d11f05c24974ed
dist/2024-11-27/rust-std-beta-x86_64-unknown-illumos.tar.xz=a952b0c2bbed9085525c041c957f00b6b1020e031149dba70c09a1a0d40db3ad
dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=817d3d3a931eba2255bd5721435cba7604fe37a72c18a179c1fd5f06dc3b97a1
dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=170a54aa50f161576d4b0d103f2ab6dcbbb81ee57a5a47f7fbd181128f6c17ff
dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=ea991dce55415ed7462abbeb1ac1c70795cb628b0460e14230e8cecd41117fca
dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=a8f620c3a641f8f4c29d88e4cc54d7637aeb18cf8eaed8571ce558835f742601
dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=875e2e3309b1deccc1a4476e4847a2849df32e0e2a394e4ddf3b4abd1feca534
dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=23f21ac664b3341771109ac69d094518a512391b86219ffec50725dc68a08504
dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=680f5b2c63f58643bd34f9921e2c1699a549410ab06bfd04ce991907e8fd7d8f
dist/2024-11-27/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=dd10f6f3ce39489b6e3f3f638573e850c36518e3b2e8ffad0c50c3143e3a8124
dist/2024-11-27/rust-std-beta-x86_64-unknown-netbsd.tar.gz=fd31ba490f0bfc53530e34e6e5ab35a52eebee616efc8ed18d473065ea885230
dist/2024-11-27/rust-std-beta-x86_64-unknown-netbsd.tar.xz=daffc01050f5cf0b5ece91717d7a4c42cd4a148c4c11f641b494d9c375df5177
dist/2024-11-27/rust-std-beta-x86_64-unknown-none.tar.gz=376d571641a9f1f75fadf951da91bb73ba94a5495d7d33389f5f914ccbec57bb
dist/2024-11-27/rust-std-beta-x86_64-unknown-none.tar.xz=ffd9e826537dc94c6d8e767ef5a61d1fcf0385b8ccbe508ff9177de0fe772939
dist/2024-11-27/rust-std-beta-x86_64-unknown-redox.tar.gz=447e434b5e40f7882d7adb6d0346629e0e3e92d0f339c7781e5a437898a84b4a
dist/2024-11-27/rust-std-beta-x86_64-unknown-redox.tar.xz=bc21caabcb492ca648e19a8f3b9dc1a1bf7792135a202831deb554ec3ea11077
dist/2024-11-27/rust-std-beta-x86_64-unknown-uefi.tar.gz=40ca7d9ebcf6610c26f2921c0560729e708f5661bf6167266e9d8cb3987ad0b3
dist/2024-11-27/rust-std-beta-x86_64-unknown-uefi.tar.xz=06966d5901f5d9accadb47c4d1e561f3f95bd050f3f8e78f30000389f39e9b6c
dist/2024-11-27/cargo-beta-aarch64-apple-darwin.tar.gz=e1a24f081ddd93b483c0f1c196bae676163db50fef0a994bc47c2a7c98c9dfa7
dist/2024-11-27/cargo-beta-aarch64-apple-darwin.tar.xz=d51a5f0669906eceeee4e09b079828e2ebf3404aaedf1fb20745339205270ee0
dist/2024-11-27/cargo-beta-aarch64-pc-windows-msvc.tar.gz=e135a5f0f83432b58d9e093c6d560b021a133707e39e1ded90a28a9967105e0f
dist/2024-11-27/cargo-beta-aarch64-pc-windows-msvc.tar.xz=1fbe65015cb8c7ab0b863ffc6f7aa72d3bf52f7830957ede8915c61a22e5b993
dist/2024-11-27/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=9d4e830e9ba582302865fcefe31883cef4a471e77d46e70838e549ca11a0fbce
dist/2024-11-27/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=233f6347a36e806dcf27ecad4906c90bb3353051f440a819989efcf091cb78b8
dist/2024-11-27/cargo-beta-aarch64-unknown-linux-musl.tar.gz=6cd719a7255a0eb1f11592b9a92d0aa4986363f624ee0d6077fcc253acab66a8
dist/2024-11-27/cargo-beta-aarch64-unknown-linux-musl.tar.xz=b874ca8285ad1936adc70a9323cf80f06322b1e6d5925f54b58500129830f0ca
dist/2024-11-27/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=ec7200319224ccabe814cb051e51d147f1ae8c763413002fd03c9263a02c2320
dist/2024-11-27/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=86e96c80a91862e59123272c80f1cfabdca56bfddcd66af4a5e840af7421c4e1
dist/2024-11-27/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=3f7cfdcb28fe8c3f0dde58c24a0c424652b40d00a24fc50891351fa5bff5c15e
dist/2024-11-27/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=2d5a184b0103ac943ec4f6756fbc7126773e739e0d120acea7b3244c7cd19b1b
dist/2024-11-27/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=9a77540943f28584d90b4bcae4e234cc9d833eb732f65d7fbd680a0f4e915da4
dist/2024-11-27/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=7696a065951b7d7179b30ff2fd16a05675b6bd4250f293666b98ec05299113a5
dist/2024-11-27/cargo-beta-i686-pc-windows-gnu.tar.gz=eaff75076ad71a4291af5465dedf0fb0998dc171e35ab8f707ac63b43e89c38a
dist/2024-11-27/cargo-beta-i686-pc-windows-gnu.tar.xz=205d3d19726a1a87a1533d94f77b73ed9de8181906acb48088dca22835aa7a83
dist/2024-11-27/cargo-beta-i686-pc-windows-msvc.tar.gz=58da319889533ff7be5c9142c2abdd1ade79de10eb83d7ef82ebd93b75607f8b
dist/2024-11-27/cargo-beta-i686-pc-windows-msvc.tar.xz=5ae699d0f6b9e210a988af5b8f2f0c4d62fb1695ed6fa55718fdf05298039b9c
dist/2024-11-27/cargo-beta-i686-unknown-linux-gnu.tar.gz=362f6338ea929ceb632307031e049dee1b3ed998f5cf160654c327c5e0e7ed39
dist/2024-11-27/cargo-beta-i686-unknown-linux-gnu.tar.xz=88f14ca7b5c8af006f3c54749b61747485f7e93fde4c65b5969e73503d12c5c2
dist/2024-11-27/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=9ee8f29e3e715cd7c85e679fd01ca724a27503a50edb0e6f8912f289630bc7a5
dist/2024-11-27/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=4c643f0d18ba101c2b248e1df32ec3ddba82efc0d5f9b47945d484fd3d462794
dist/2024-11-27/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=f70952c63e2eebd05acc326cfa667595535fc36db34bc0262fda4ba100ff2145
dist/2024-11-27/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=0546a908cc12884801c35b461f98db01e87a7f92d276ca6cb6b89eb76c596e2c
dist/2024-11-27/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=3534e839b34603e4e2b32fb8ecc76163ea3b9cd9907c1a22fde4165860d1fb56
dist/2024-11-27/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=b402a2e73debd81dc5cbc866f00c2ca82f676e2f923193674969af0ab34ad311
dist/2024-11-27/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=fa69011557fdde5af1f78f33f9ba75a1d6f4488b9d8edd2958582593dba347fe
dist/2024-11-27/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=679be0bf62c7371b92f1824c8718662672ac3ef2d79e8af5c752fe34effbe333
dist/2024-11-27/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=ecc2ba0da5c1057136eb105ec0727e55396e414d75efe0c2b96bef0477961574
dist/2024-11-27/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=a89ad44842df861c69c6633ba79bf4ecefc38419d5669b6f22a265dd7be836f2
dist/2024-11-27/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=051437ff7d177bdeb7a5a0eb947d27b8cf352c8e809b9311a1cc21b785a5a8b5
dist/2024-11-27/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=1a4f50972104a95c404e778279a4acd42176cae45f58d316d601e7f38dc7bbc0
dist/2024-11-27/cargo-beta-s390x-unknown-linux-gnu.tar.gz=bbe9812fe890b900e71aa4714dabd2f3e67bdc610fe0bbd5aea645ee807dd0ff
dist/2024-11-27/cargo-beta-s390x-unknown-linux-gnu.tar.xz=eebac7e8555f44ea9094750b61bd11d758197a72d4d436e1713e4bca42fa8080
dist/2024-11-27/cargo-beta-x86_64-apple-darwin.tar.gz=6773b94f012a3d3589e2bca28f35dd23208fb245f107e4a17b8b3e7f893c038a
dist/2024-11-27/cargo-beta-x86_64-apple-darwin.tar.xz=d3a20dbd60545b0162dc06499317e342bea077cff369e053eb89e85e2b640188
dist/2024-11-27/cargo-beta-x86_64-pc-windows-gnu.tar.gz=39e16c97c0b22533dfa674d6e8f5bf5df256e2b426d02dca5ed33e246f18d05b
dist/2024-11-27/cargo-beta-x86_64-pc-windows-gnu.tar.xz=ffd939f901c64a17c3f24fc69744cd2af1c176a45d8e5fa8209067ada403db7d
dist/2024-11-27/cargo-beta-x86_64-pc-windows-msvc.tar.gz=8addc12e74a983f3166b89d1d53ce87c92f38c7c3a62ec7c66580aa424d20516
dist/2024-11-27/cargo-beta-x86_64-pc-windows-msvc.tar.xz=8e5622917395ff50e53b237e7322f1faf2b64f0446c41ccaa0096e57a3e7de69
dist/2024-11-27/cargo-beta-x86_64-unknown-freebsd.tar.gz=2734d099aa1ada79346213aec8cc7ebe40312df1dfb40a32d09ccd3b6622e025
dist/2024-11-27/cargo-beta-x86_64-unknown-freebsd.tar.xz=642edcaf16dd74c0935d28ce9b37cf1c5ecb9c03bec30f6ff0e7476760ae7ca2
dist/2024-11-27/cargo-beta-x86_64-unknown-illumos.tar.gz=4f28de38005de48db7126dcb698b748063341de41dc71175605301837a3f7336
dist/2024-11-27/cargo-beta-x86_64-unknown-illumos.tar.xz=ce18692f99780ec09d01816277ee4e71785bdfbd7abb4375ba8d87c1b6905ffa
dist/2024-11-27/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=f1d692c3a1c280f34de167ef26af3c13a6d0a3b5ae4fb86b0a9f2178c3287a94
dist/2024-11-27/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=21f477af2b49ec8809bf8bc7b4c4919c7d2ac57782b829f5a0d9ef1967c5d71a
dist/2024-11-27/cargo-beta-x86_64-unknown-linux-musl.tar.gz=4bed61be221c1347b1649f54222b27e2a3577b84816ce1099c9f0f461c6e9e5a
dist/2024-11-27/cargo-beta-x86_64-unknown-linux-musl.tar.xz=33f463209d50ca6b04a8953c87d2177a84d1729d635de9a7c9b1a711ccb5d751
dist/2024-11-27/cargo-beta-x86_64-unknown-netbsd.tar.gz=ce46b5b2d767cc0d790d8fd21052ecfb787dffb4218a238a339fe5f1afd26d6f
dist/2024-11-27/cargo-beta-x86_64-unknown-netbsd.tar.xz=0afd0489cb4231edc5bc1ef24a43c3f1918f681f08c1207d184fefdb46416509
dist/2024-11-27/clippy-beta-aarch64-apple-darwin.tar.gz=6e5f1a85dad2b899567369aceac0102943ab807dad7e218c273b7b4d6393dba7
dist/2024-11-27/clippy-beta-aarch64-apple-darwin.tar.xz=f784ac4a6ab180675396adf8256ac2bf2d1e823bef106d1c6c59911a8360692c
dist/2024-11-27/clippy-beta-aarch64-pc-windows-msvc.tar.gz=22f1e9299a24aebaf9a32471ddc6cdbf856b455d059ca077170aecf5989f8772
dist/2024-11-27/clippy-beta-aarch64-pc-windows-msvc.tar.xz=7f3fd047ed5aa85ea6ca2b0d6103f7530d7d070c93b0f212c9d1a6491f160cbc
dist/2024-11-27/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=f383ecb5cd654268f00be1f577572993c38e7386a1e1d18b864338e87c7b2b42
dist/2024-11-27/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=b2043facf587f98a8f10a92ae129b7f608297709f4ac61d683b7c813cc65e41e
dist/2024-11-27/clippy-beta-aarch64-unknown-linux-musl.tar.gz=6678d45195bd2a7b27ed2d4bad3790e6b63e376da71d112b9333760ea375c40f
dist/2024-11-27/clippy-beta-aarch64-unknown-linux-musl.tar.xz=f6c77e80c9ea4e312fc2715a9f66ea9a2e6344e3f04ab96cc572e4c0e8c915db
dist/2024-11-27/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=be8c0dfde3f09bf476d6600b530aa498b01415015665429bebed8814c7568b73
dist/2024-11-27/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=4315f7623dcf0a278cccb6c8b397a29f83f70ecb9b03588f61e383e5ebaa697d
dist/2024-11-27/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=c31ff694c68f28e0f462133e783a5d732cf9c539737fc8dbbfd01a53e9a456c3
dist/2024-11-27/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=2553ae5596b8273d8a61ec66d2e20d0c9733c9f791ca5c56217c60884f0ccf9a
dist/2024-11-27/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=1842cf2c26ab474df47e74720c56997e270b37609f840ac50ab0b05064cb38fb
dist/2024-11-27/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=e882b1cc2814e3c97c33991fa0a80de62556ce8f4f88307f6338a90be32b045b
dist/2024-11-27/clippy-beta-i686-pc-windows-gnu.tar.gz=7c6e08b841f21e3b8953e51a6a9fd9df0c719e8defd7b1ab0660d8920fe72185
dist/2024-11-27/clippy-beta-i686-pc-windows-gnu.tar.xz=137aec194877446fec994a233427db419bb4f2910151c456c3ec80d9329628e7
dist/2024-11-27/clippy-beta-i686-pc-windows-msvc.tar.gz=52ba38277ac3f80d124fdc8dd1709b8c1115cecfc53fae4731da8615a63f78cb
dist/2024-11-27/clippy-beta-i686-pc-windows-msvc.tar.xz=548d3eb599334ab98791b8ba27decff8b0de98dfcffadc994ad38aad6255cff5
dist/2024-11-27/clippy-beta-i686-unknown-linux-gnu.tar.gz=448071394d5e647e8da8f64cfbf85e8305d85ff9357dd24737523c95eb339ab3
dist/2024-11-27/clippy-beta-i686-unknown-linux-gnu.tar.xz=e25daa6264cf5e0a7cbcfd827e27a8e276c29c88c86cc15977c1a1650d0303f9
dist/2024-11-27/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=9f080cc937e7209ad83fdb8bf4b2cd7b080af83dbd9061229f154785e273bfec
dist/2024-11-27/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=7d537f66195c581ff51ce8f53c4687a762daf225c7f0ce76393953ab04b804e1
dist/2024-11-27/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=2bd38261a9ef33ad687b3edcd33f283c32a493a80b56dbefc822c1116edb1f2f
dist/2024-11-27/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=7e63dff1d8abe517aefeb4b1976932d23a9a7ed5e4db2398d8ba2659301f639c
dist/2024-11-27/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=1495b2a49cfce014da72beb691e6c477d189ef34080acb1761b588d11b75d27a
dist/2024-11-27/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=75da94f1ade2ef48674b77ded595c69ee715f62f9d9dd96e72039e27807b7314
dist/2024-11-27/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=2d6b826fb4d3d9b61ecd3aaffdd1334f766dd5a5fb0d8279e0de26d381c5cbdc
dist/2024-11-27/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=f5ceaca2651d6002f232f71809458ad912bb5f00030790e907ff7b0e12c9e0c1
dist/2024-11-27/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=1a62f307197c6fd08fbeabef89f58842cfd59c6d62f530850592fe55852d61f7
dist/2024-11-27/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=4c65fd6a5d74527391fbc7c242a2313e5290209f5a15763d74eeaa6cba0a0ed0
dist/2024-11-27/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=8ab9f735a98de1949e65d51c3050b29ceba3ddc28167ba0180353253dc726392
dist/2024-11-27/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=0367eb23a9349ebd829d59fe0a2638557c8e57205e48f66a701b238461385bf2
dist/2024-11-27/clippy-beta-s390x-unknown-linux-gnu.tar.gz=ffe9100ec6b81b081d5f9d840bdf01c658790d7e6bc0674e5ebb6b28f79c2f7f
dist/2024-11-27/clippy-beta-s390x-unknown-linux-gnu.tar.xz=b19b1b28bb7ddf8cf977f102acb623f65d5117c44ab8b62cf197f2d3d33c15de
dist/2024-11-27/clippy-beta-x86_64-apple-darwin.tar.gz=d986de5c01bde3469693dea7cb4248155ee9791550aa179d601066d27e45afb1
dist/2024-11-27/clippy-beta-x86_64-apple-darwin.tar.xz=8000e46ccc2598fdb770c69c68aeb18d94db9b2847d0509f7a9c51ef28714ba7
dist/2024-11-27/clippy-beta-x86_64-pc-windows-gnu.tar.gz=c701581f28d885889ae5c845a7b34beebb04a4631c2740e9333b69390cfaf499
dist/2024-11-27/clippy-beta-x86_64-pc-windows-gnu.tar.xz=fc285792e6f626e133edede613a9a9a90ee12191765e2f0beac642a3b3c9ca12
dist/2024-11-27/clippy-beta-x86_64-pc-windows-msvc.tar.gz=91afdb71bdd54e5c04fc7c933dac06d5e769627e886e20eb712524e852a01966
dist/2024-11-27/clippy-beta-x86_64-pc-windows-msvc.tar.xz=2ef7018c7319e3a299c5eddf36748d9d293ae43eaf54662d9855fd211eb4658c
dist/2024-11-27/clippy-beta-x86_64-unknown-freebsd.tar.gz=02234d4c47478112e01d51bc7dd48cd467293e1eeba55bd383d08bc7376c471d
dist/2024-11-27/clippy-beta-x86_64-unknown-freebsd.tar.xz=a3e6a0c7f31278866d97816c5ed434b1987e0bc5a89b24283e836402803c1388
dist/2024-11-27/clippy-beta-x86_64-unknown-illumos.tar.gz=b238ab536ac963929884da4dc9bab43679e6fa9aba4251c73ab7e5cbe5d8eeb9
dist/2024-11-27/clippy-beta-x86_64-unknown-illumos.tar.xz=797ea7a7643a8302e45347f21c4dc6bdee617c2a9d9ccef74ed525c7d2e9dd91
dist/2024-11-27/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=d630a6b25a08af85d3d426e73d3231e018e0ab7176a5934572786147fbbf3823
dist/2024-11-27/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=d0259a0112f452ee49b8c9bebd760ab8945e5bc3a0d57b1cdc2b8e24accd35c7
dist/2024-11-27/clippy-beta-x86_64-unknown-linux-musl.tar.gz=5febe478e5040f0f74a14c23e78eed21b080900d875d6b447354945c07677a6f
dist/2024-11-27/clippy-beta-x86_64-unknown-linux-musl.tar.xz=552c35bbe76a83439e66cf9ccd522d97e43a8fe4f6aadbabd1f02c4b2c1814dd
dist/2024-11-27/clippy-beta-x86_64-unknown-netbsd.tar.gz=ff6db2d7b84e1b01c81e494de15ccd07f60fef6dc60fa46d47e128ebaba4022c
dist/2024-11-27/clippy-beta-x86_64-unknown-netbsd.tar.xz=b27f89b175bee3769dab1c2d0c54f17ff3efba2038f3b600f4077435c7fd21d3
dist/2024-11-27/rustfmt-nightly-aarch64-apple-darwin.tar.gz=5b5015483d0a98e9dc715c3cc8c23598c02fc14ea6e5878790ae68f2f1c8ef46
dist/2024-11-27/rustfmt-nightly-aarch64-apple-darwin.tar.xz=ce5706f0397a1b2fd9e17dbf34ccfbc3e8c87cc81c92b54b81fd33accc2b7c06
dist/2024-11-27/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=3f5077c8743b5c4f233da7d0aa0aa13fc488ef0fa9da24b002bfa413d52dc845
dist/2024-11-27/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=087eb30f24ba7d8ee42e28bce2a6cd75e5fb7ef5dca8a738ef23fac82ad59566
dist/2024-11-27/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=28a716ef9c5318543559ab4c0c2d062b0deeab1ecec80d5d83ad5effb574f209
dist/2024-11-27/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=99cf9ec4b7bea4281f64a613784350a8ac34e9b0387fed7eb26d6f8c21c83735
dist/2024-11-27/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=a23c3de89603bd4d1035a267e6ee456c6de12efa4029d76ded3edf7c69285a15
dist/2024-11-27/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=462dfd28b631b5a6d8277920cfa8037d8583cbf6a2e5c9159c492161013e820a
dist/2024-11-27/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=44af5b13726cab40865580df8bc05182a2359eae64e41a92f84790ef55ca6bdb
dist/2024-11-27/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=0a7c0b207e745d01194d96f0fbe2402273d630d4f1aa05001a5f5371c9585a2c
dist/2024-11-27/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=66e2fc688b8f746d15c0dce042f2a94e06c5b652d5e0b6534d9e992eec186784
dist/2024-11-27/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=15a2e087f7b482fa8c027fe6e6fbaf846d784c8e917fed375048a297d5e13c45
dist/2024-11-27/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=71788ea2544f8349ec548a2f150dca2afe80a49deb91c00c46484a5e3039742d
dist/2024-11-27/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=d9fa7b780b9d8b93549abf0a3f0e6f31cc8e1e991ddf682adf3b616fe2a1f0c8
dist/2024-11-27/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=30924bad51ffa62f762d4c000f86ea3457b590f6397d65755c711ff7f77ac129
dist/2024-11-27/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=14fff13942e6a65927776c49013249b2e75aa3a630667ecf49c9ba721e47bcb4
dist/2024-11-27/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=02d82688bdf3bd3c261a4a6d4acfb07835e29ce262cdc3165ba849a6a8490bcc
dist/2024-11-27/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=2a19b55bb609542ec49dea87e3b67532e5d18df8be43d0ad775bb34f4f9f96a0
dist/2024-11-27/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=d07ca0ddfb0dd89a9cc935b2b9662379bcc9503cb28a28d68c5165f787a7d762
dist/2024-11-27/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=de8106801b1e49dfd8a4fffbfc2a4f949218eaa011ca2085953ebf2a5ea9b141
dist/2024-11-27/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=309024f86e80a4568721b5bb61aa936e027accc251fa97acd5043b513b325576
dist/2024-11-27/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=55bf234aa2ec7fd4c6a7179f779d790e7f62969967519bacfeae84db5cd29abe
dist/2024-11-27/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=4bf9571182e7ef40e76c7e5905fab8ac35269ace390f5007480b4951f80cfa3b
dist/2024-11-27/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=2a2cde80fcbf68768ba7a99cb059a0cdc9313ad0c934383dde9598d6147ef756
dist/2024-11-27/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=b747fb16b15cff3f9368ce1a1f5cad0d2930bde5a609547a3afa2679d7ab8a1a
dist/2024-11-27/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=b861f8361ee806d83f38afbbbf312e0e5e4d8851e7048444c409de1a83484446
dist/2024-11-27/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=ebe56700ad0948e4dcd9930730f7df8e01a5eefca1d1157fe12160d782e2a5c0
dist/2024-11-27/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=5081c9b8677314464d8a3a50220809def18badb2269d2cd8b7106f3547b0e25a
dist/2024-11-27/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=2ed9094b538b6450371311b742f2d309a1f40b2b4c84deb9867059336b76d1b0
dist/2024-11-27/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=d9d52d9b9f4da7a457d05dd4645885d092f170bd2f751a49b4ab3b88395a5248
dist/2024-11-27/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=a2e51d381645c6bf18502ca72fe9f10ffd309281dae87ec16c5627f232f77e50
dist/2024-11-27/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=c526efc054c33a08626b882eebadf887a9aaf8fd60a4adf6a146659a7c1ec8d7
dist/2024-11-27/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=04e5b7c97b57ff7d967abb4f98374f0833108c04f6edf482b8b3fefbde340956
dist/2024-11-27/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=1829afdebce1c3fe249f81958de68c765db18b431927e54fc42be37ea4ab8226
dist/2024-11-27/rustfmt-nightly-x86_64-apple-darwin.tar.gz=d6cf138d02e50168f8ee4a89abb2a4a39e19458d060d7b46cf227bba1fd4c0d8
dist/2024-11-27/rustfmt-nightly-x86_64-apple-darwin.tar.xz=e8185262c82c064c4bb9ae6f1d3072819410de9cfca943b77605012a546c254e
dist/2024-11-27/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=64d78f9f05a978b95b9e22a63bbb31dcf98152df5638f498a361a96d9d2b0c04
dist/2024-11-27/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=c07041ab84364ace58a357c18b5c4dca037852e1159edabb02f4579ac6853b4a
dist/2024-11-27/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=7ef0122ccd3a0c77c917bd75e93358eb95d7e87d78a165c724e3f0cd90f8209c
dist/2024-11-27/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=d0d0566a0a50e1e9e7f4251cf207bde82d96c27016f0a0acc364754561ab4881
dist/2024-11-27/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=e4854528c31316894339bfa97b07ec607e8956877c285778e555885ce9c8a068
dist/2024-11-27/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=d79c9b352ed7b2f132f06dcdf360527502b2153beb09cca968a5ced521edcd39
dist/2024-11-27/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=df76cbeae0a61506a29db22e8743d16fcd97ef2da216ea15bf4d6cd709814017
dist/2024-11-27/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=103cbb30bbe92da6666d84fab53dd7fe8105c2ebe62eeab5f6609488e62a481b
dist/2024-11-27/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=5f3c61663a319d6162240192f387e10ab87e2a972062198082158a243b667d7f
dist/2024-11-27/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=221b45c3928b1c45fedbeea987ad80750d3f55fbc564cf3ccf910a68447ad725
dist/2024-11-27/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=18eb24fd665ce1cc4ce66b37b19c22397bff9369963b127137780870c179228d
dist/2024-11-27/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=bcd09587a21ea10953a14521e9e0ba7b5100e8e15b6a10cc4e7bd359200d5279
dist/2024-11-27/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=db712c5e1d21231770e12dc95f6bcbe2f1d04b9cde61bc7adf8b529b41773adf
dist/2024-11-27/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=43303e426752dcd15964416822cdce0e5f3012366a9b77f3d68e6011c7bacd0f
dist/2024-11-27/rustc-nightly-aarch64-apple-darwin.tar.gz=95d543a835b11cb5ccbf0578df1ce4e1846e4915622d23a36cc6e18e44e17f29
dist/2024-11-27/rustc-nightly-aarch64-apple-darwin.tar.xz=db9e0c51c35c81c2ec8be0838f3231f7374917215792ffee159e3d7ffed855d8
dist/2024-11-27/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=bf9b83d6418bf97caf2df70a8e8298cd8fecb7b950cdaaa2cecbec243ed57c74
dist/2024-11-27/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=bb520da5b522fffb5a20eed4390990c2ab9d22eb4f77196535a84ae7a434c9f5
dist/2024-11-27/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=4072d9ca2d617d09d394139c0b8608bb8b2b8b2b4fa450f13c41975a16a791c7
dist/2024-11-27/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=3d75a8a534e86bb55b63f5b5b2df66ae47862cb7f3ecd1591a829435031d7279
dist/2024-11-27/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=3cf05e90bc1f95e92cca4769f74055245234037009cf464df3062238c88bc2b6
dist/2024-11-27/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=245ebb7886cfba64d667630ca8bd672520cfece0ccec3b916e3de0f26aeada52
dist/2024-11-27/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=dadff4abd2f169f9aa1910d4ea247b7d1f767fca74238ad31485b73399ab6dda
dist/2024-11-27/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=ff97e1201e9a305673e8a9b740b7696cc4cb5e86bfaa3e137cd8e3e28cffd7a6
dist/2024-11-27/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=0c411e0824140323f51600d387d52bd01f601f5539d6457815e950224a6d29a4
dist/2024-11-27/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=dc5731a70c393f69555433d522cde8a52893bfb88beec519c1bbb03b2a0e060c
dist/2024-11-27/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=01ef2f07f1222fbf3e0cfc5b957c287fb886fd0bd08cbf18f90dc37fb0b63541
dist/2024-11-27/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=d45042b3ea0c0ce6befea7bfdd731e890dbd1f47d1992fe8718a1363f9f18779
dist/2024-11-27/rustc-nightly-i686-pc-windows-gnu.tar.gz=5437da4c0b73d203789829512d856a66c1697d95afb1ffeaa6347ad0f7c04672
dist/2024-11-27/rustc-nightly-i686-pc-windows-gnu.tar.xz=a7cb4cb627d75de1ade9211d8ea489ada9ac76ed38909751861ef0cb729dcbcd
dist/2024-11-27/rustc-nightly-i686-pc-windows-msvc.tar.gz=fd6ee6fc171459092e5e8a012d9cfb7491313e021d1c38965605836b5b101b0a
dist/2024-11-27/rustc-nightly-i686-pc-windows-msvc.tar.xz=314c7cd558a3654db85d75b3ed71da7cfec3614e4a5f2c449dbc6663b64c7e3d
dist/2024-11-27/rustc-nightly-i686-unknown-linux-gnu.tar.gz=7a1118011b11befb7df2df57e4450c7611bb3503b3b3cfece9c9c7d4a304391d
dist/2024-11-27/rustc-nightly-i686-unknown-linux-gnu.tar.xz=2cb95208e77546bcce56d8d5646c3fb5e49ed711894926cb50903ba10431a36e
dist/2024-11-27/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=4a76c4493e5ba19aaf14947a6c2e28ebfc7f2da530f1441a9fdfa328e15ea4cf
dist/2024-11-27/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=9b361904c691e17fbf44d80c7f7789511db1d8f251d65ba9cf6fda7f06fd495f
dist/2024-11-27/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=e89dc76ab061ae23081aee1619fcbf4a94e3acefef6b9b149231f3e1c22f9ec1
dist/2024-11-27/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=11266d557e6d1d9155e6f04f65e4815cfbfd9f8e1aaa47221030e3ff11b22f78
dist/2024-11-27/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=30f2eae1b8694607a04c836f750b4b7c204e1e14e52ec37885b9a821c2c9646e
dist/2024-11-27/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=495316e70b26140c66b074e9d7f714ab949f422c2635cab784a5e133538e4bb9
dist/2024-11-27/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=ca560c4fe28051573d54f512652ac9740a2d1111aeb8e36b004a6ff9c325925c
dist/2024-11-27/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=1191f15bb6da98b01b43f0e9d7f51c5c45d38e3c5be2b4ae5f7c0c8fd25e9a90
dist/2024-11-27/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=5f85829aaab919fa4b2fa5ac843b87358e8da4797adbb6eeaed5be02666ce964
dist/2024-11-27/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=7c671d366fec561f0b568bfb4b6a08a6071303077a60f76da1307453e51ebc36
dist/2024-11-27/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=300307ab6cf88afc4312edaa510769e901598492deec4834176c6fc9f3eef6cb
dist/2024-11-27/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=6fcf91c8679f4963f7d510cc8afbc24a1070b25ea6d20d5d31ad78ea659da194
dist/2024-11-27/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=ab905f6f3119648c83a2f37ebe1a55b7899a5ac6d10070e4dbbfb89762a369af
dist/2024-11-27/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=13688b6857c8b10f7fb497f07c969d406cb6b76869957b5138f4b20fcc5d7c5a
dist/2024-11-27/rustc-nightly-x86_64-apple-darwin.tar.gz=e6bb782014e34fafdc5dcf3aeb407eb636d822d346c5a8c6227cc45bc645561a
dist/2024-11-27/rustc-nightly-x86_64-apple-darwin.tar.xz=6016ae620deddc42d1d6b6134b0164dab45a204089754b73db41ec837aa88a84
dist/2024-11-27/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=ed3a381858612e25cacfd89c08496e9d06378d593ccedea4217ad4fa1ab326d4
dist/2024-11-27/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=4819bb9c25aa743de7ab7e93b10b30336a87f1f75e5122d578df2c83fbc59850
dist/2024-11-27/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=404aac87c77871c80f83cd7c59390af9af704ee468f40eba68d224d23e2c84e9
dist/2024-11-27/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=0e1e0d2454ad24fe1da2cce2dce425bc1167bbca68832da2476c7996c00ba612
dist/2024-11-27/rustc-nightly-x86_64-unknown-freebsd.tar.gz=946d5bcc3ac0b83fd0b53b60290a6361b179f16ba2aa6a2467789ad520278792
dist/2024-11-27/rustc-nightly-x86_64-unknown-freebsd.tar.xz=f3bd1a053399ec89dccaa7456da41d54a8e91deb5c628e4c502fdcf34c5fe780
dist/2024-11-27/rustc-nightly-x86_64-unknown-illumos.tar.gz=c353588a38705b7ae050d4b9868b6c4d3527295edbfb25c115b22cda4912be1f
dist/2024-11-27/rustc-nightly-x86_64-unknown-illumos.tar.xz=a71d8b2b42f6cd522da237f99492ed59cd34ea8c86fc1e73c8854c8234e1c980
dist/2024-11-27/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=5116b949572fd6c7b11a079d9453b15a4c48562bce22b26d82b7050da772789b
dist/2024-11-27/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=3635df40363273d44c6f8182f5f6a3a099ed55897bb764cab2565363cd31c1f4
dist/2024-11-27/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=5233af0b907fb7b176d2b5fee07c486e92dcbbbab1d54a60d814a827befaa984
dist/2024-11-27/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=c908cad6d28657f1fdcbe9d84ecb86f247c75134803dd5273ca24c6c68a58f37
dist/2024-11-27/rustc-nightly-x86_64-unknown-netbsd.tar.gz=c799165c319218a2fb4cdc0ac8db87fc9e2992a8e402d984ea27938a5ad1c5af
dist/2024-11-27/rustc-nightly-x86_64-unknown-netbsd.tar.xz=ec12763fa5d4cc150f663361cd245c30835e05e3b1928898b1b7300de559468c

Some files were not shown because too many files have changed in this diff Show more