diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9bde9c4fbffc..f91e6816ae42 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -286,6 +286,10 @@ jobs: - name: x86_64-gnu-distcheck os: ubuntu-20.04-8core-32gb env: {} + - name: x86_64-gnu-llvm-17 + env: + RUST_BACKTRACE: 1 + os: ubuntu-20.04-8core-32gb - name: x86_64-gnu-llvm-16 env: RUST_BACKTRACE: 1 diff --git a/Cargo.lock b/Cargo.lock index 6c96f415f44c..7aa243ad8b52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1663,9 +1663,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" dependencies = [ "ahash", "allocator-api2", @@ -1982,7 +1982,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown 0.14.2", "rustc-rayon", "serde", ] @@ -2621,7 +2621,7 @@ dependencies = [ "compiler_builtins", "crc32fast", "flate2", - "hashbrown 0.14.0", + "hashbrown 0.14.2", "indexmap 2.0.0", "memchr", "rustc-std-workspace-alloc", @@ -5095,7 +5095,7 @@ dependencies = [ "core", "dlmalloc", "fortanix-sgx-abi", - "hashbrown 0.14.0", + "hashbrown 0.14.2", "hermit-abi 0.3.2", "libc", "miniz_oxide", @@ -5415,7 +5415,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4db52ee8fec06e119b692ef3dd2c4cf621a99204c1b8c47407870ed050305b9b" dependencies = [ "gimli", - "hashbrown 0.14.0", + "hashbrown 0.14.2", "object", "tracing", ] diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index 207ae8ad844b..dda466b026d9 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -137,6 +137,20 @@ builtin_macros_format_positional_after_named = positional arguments cannot follo .label = positional arguments must be before named arguments .named_args = named argument +builtin_macros_format_redundant_args = redundant {$n -> + [one] argument + *[more] arguments + } + .help = {$n -> + [one] the formatting string already captures the binding directly, it doesn't need to be included in the argument list + *[more] the formatting strings already captures the bindings directly, they don't need to be included in the argument list + } + .note = {$n -> + [one] the formatting specifier is referencing the binding already + *[more] the formatting specifiers are referencing the bindings already + } + .suggestion = this can be removed + builtin_macros_format_remove_raw_ident = remove the `r#` builtin_macros_format_requires_string = requires at least a format string argument diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 1238773d58b5..fde4270334b6 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -646,6 +646,27 @@ pub(crate) struct FormatPositionalMismatch { pub(crate) highlight: SingleLabelManySpans, } +#[derive(Diagnostic)] +#[diag(builtin_macros_format_redundant_args)] +pub(crate) struct FormatRedundantArgs { + #[primary_span] + pub(crate) span: MultiSpan, + pub(crate) n: usize, + + #[note] + pub(crate) note: MultiSpan, + + #[subdiagnostic] + pub(crate) sugg: Option, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(builtin_macros_suggestion, applicability = "machine-applicable")] +pub(crate) struct FormatRedundantArgsSugg { + #[suggestion_part(code = "")] + pub(crate) spans: Vec, +} + #[derive(Diagnostic)] #[diag(builtin_macros_test_case_non_item)] pub(crate) struct TestCaseNonItem { diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 4b5c777f4ad6..214fed8e2d82 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -1,3 +1,4 @@ +use parse::Position::ArgumentNamed; use rustc_ast::ptr::P; use rustc_ast::tokenstream::TokenStream; use rustc_ast::{token, StmtKind}; @@ -7,7 +8,9 @@ use rustc_ast::{ FormatDebugHex, FormatOptions, FormatPlaceholder, FormatSign, FormatTrait, }; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{Applicability, MultiSpan, PResult, SingleLabelManySpans}; +use rustc_errors::{ + Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, PResult, SingleLabelManySpans, +}; use rustc_expand::base::{self, *}; use rustc_parse_format as parse; use rustc_span::symbol::{Ident, Symbol}; @@ -364,8 +367,8 @@ fn make_format_args( let mut unfinished_literal = String::new(); let mut placeholder_index = 0; - for piece in pieces { - match piece { + for piece in &pieces { + match *piece { parse::Piece::String(s) => { unfinished_literal.push_str(s); } @@ -513,7 +516,17 @@ fn make_format_args( // If there's a lot of unused arguments, // let's check if this format arguments looks like another syntax (printf / shell). let detect_foreign_fmt = unused.len() > args.explicit_args().len() / 2; - report_missing_placeholders(ecx, unused, detect_foreign_fmt, str_style, fmt_str, fmt_span); + report_missing_placeholders( + ecx, + unused, + &used, + &args, + &pieces, + detect_foreign_fmt, + str_style, + fmt_str, + fmt_span, + ); } // Only check for unused named argument names if there are no other errors to avoid causing @@ -580,6 +593,9 @@ fn invalid_placeholder_type_error( fn report_missing_placeholders( ecx: &mut ExtCtxt<'_>, unused: Vec<(Span, bool)>, + used: &[bool], + args: &FormatArguments, + pieces: &[parse::Piece<'_>], detect_foreign_fmt: bool, str_style: Option, fmt_str: &str, @@ -598,6 +614,26 @@ fn report_missing_placeholders( }) }; + let placeholders = pieces + .iter() + .filter_map(|piece| { + if let parse::Piece::NextArgument(argument) = piece && let ArgumentNamed(binding) = argument.position { + let span = fmt_span.from_inner(InnerSpan::new(argument.position_span.start, argument.position_span.end)); + Some((span, binding)) + } else { None } + }) + .collect::>(); + + if !placeholders.is_empty() { + if let Some(mut new_diag) = + report_redundant_format_arguments(ecx, &args, used, placeholders) + { + diag.cancel(); + new_diag.emit(); + return; + } + } + // Used to ensure we only report translations for *one* kind of foreign format. let mut found_foreign = false; @@ -685,6 +721,76 @@ fn report_missing_placeholders( diag.emit(); } +/// This function detects and reports unused format!() arguments that are +/// redundant due to implicit captures (e.g. `format!("{x}", x)`). +fn report_redundant_format_arguments<'a>( + ecx: &mut ExtCtxt<'a>, + args: &FormatArguments, + used: &[bool], + placeholders: Vec<(Span, &str)>, +) -> Option> { + let mut fmt_arg_indices = vec![]; + let mut args_spans = vec![]; + let mut fmt_spans = vec![]; + + for (i, unnamed_arg) in args.unnamed_args().iter().enumerate().rev() { + let Some(ty) = unnamed_arg.expr.to_ty() else { continue }; + let Some(argument_binding) = ty.kind.is_simple_path() else { continue }; + let argument_binding = argument_binding.as_str(); + + if used[i] { + continue; + } + + let matching_placeholders = placeholders + .iter() + .filter(|(_, inline_binding)| argument_binding == *inline_binding) + .map(|(span, _)| span) + .collect::>(); + + if !matching_placeholders.is_empty() { + fmt_arg_indices.push(i); + args_spans.push(unnamed_arg.expr.span); + for span in &matching_placeholders { + if fmt_spans.contains(*span) { + continue; + } + fmt_spans.push(**span); + } + } + } + + if !args_spans.is_empty() { + let multispan = MultiSpan::from(fmt_spans); + let mut suggestion_spans = vec![]; + + for (arg_span, fmt_arg_idx) in args_spans.iter().zip(fmt_arg_indices.iter()) { + let span = if fmt_arg_idx + 1 == args.explicit_args().len() { + *arg_span + } else { + arg_span.until(args.explicit_args()[*fmt_arg_idx + 1].expr.span) + }; + + suggestion_spans.push(span); + } + + let sugg = if args.named_args().len() == 0 { + Some(errors::FormatRedundantArgsSugg { spans: suggestion_spans }) + } else { + None + }; + + return Some(ecx.create_err(errors::FormatRedundantArgs { + n: args_spans.len(), + span: MultiSpan::from(args_spans), + note: multispan, + sugg, + })); + } + + None +} + /// Handle invalid references to positional arguments. Output different /// errors for the case where all arguments are positional and for when /// there are named arguments or numbered positional arguments in the diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index a8cee5a61edb..5218f772484f 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -884,6 +884,9 @@ fn collect_nonexhaustive_missing_variants<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>, column: &[&DeconstructedPat<'p, 'tcx>], ) -> Vec> { + if column.is_empty() { + return Vec::new(); + } let ty = column[0].ty(); let pcx = &PatCtxt { cx, ty, span: DUMMY_SP, is_top_level: false }; diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index f0c4be2327ce..736b495343e9 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1717,7 +1717,7 @@ fn windows_unix_socket_exists() { let tmp = tmpdir(); let socket_path = tmp.join("socket"); - // std doesn't current support Unix sockets on Windows so manually create one here. + // std doesn't currently support Unix sockets on Windows so manually create one here. net::init(); unsafe { let socket = c::WSASocketW( @@ -1728,7 +1728,16 @@ fn windows_unix_socket_exists() { 0, c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT, ); - assert_ne!(socket, c::INVALID_SOCKET); + // AF_UNIX is not supported on earlier versions of Windows, + // so skip this test if it's unsupported and we're not in CI. + if socket == c::INVALID_SOCKET { + let error = c::WSAGetLastError(); + if env::var_os("CI").is_none() && error == c::WSAEAFNOSUPPORT { + return; + } else { + panic!("Creating AF_UNIX socket failed (OS error {error})"); + } + } let mut addr = c::SOCKADDR_UN { sun_family: c::AF_UNIX, sun_path: mem::zeroed() }; let bytes = socket_path.as_os_str().as_encoded_bytes(); addr.sun_path[..bytes.len()].copy_from_slice(bytes); diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index c04121a8bee6..9a2fcb0ce0a1 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -57,9 +57,9 @@ COPY host-x86_64/dist-x86_64-linux/build-clang.sh /tmp/ RUN ./build-clang.sh ENV CC=clang CXX=clang++ -# rustc-perf version from 2023-05-30 +# rustc-perf version from 2023-10-22 # Should also be changed in the opt-dist tool for other environments. -ENV PERF_COMMIT 8b2ac3042e1ff2c0074455a0a3618adef97156b1 +ENV PERF_COMMIT 4f313add609f43e928e98132358e8426ed3969ae RUN curl -LS -o perf.zip https://ci-mirrors.rust-lang.org/rustc/rustc-perf-$PERF_COMMIT.zip && \ unzip perf.zip && \ mv rustc-perf-$PERF_COMMIT rustc-perf && \ diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile index 1e2b802e64e3..c177e7387fc8 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile @@ -38,6 +38,10 @@ RUN sh /scripts/sccache.sh # LLVM, rather than the typical src/llvm-project LLVM. ENV NO_DOWNLOAD_CI_LLVM 1 +# This is not the latest LLVM version, so some components required by tests may +# be missing. +ENV IS_NOT_LATEST_LLVM 1 + # Using llvm-link-shared due to libffi issues -- see #34486 ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile new file mode 100644 index 000000000000..76846f1fed7f --- /dev/null +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile @@ -0,0 +1,50 @@ +FROM ubuntu:23.10 + +ARG DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y --no-install-recommends \ + g++ \ + gcc-multilib \ + make \ + ninja-build \ + file \ + curl \ + ca-certificates \ + python3 \ + git \ + cmake \ + sudo \ + gdb \ + llvm-17-tools \ + llvm-17-dev \ + libedit-dev \ + libssl-dev \ + pkg-config \ + zlib1g-dev \ + xz-utils \ + nodejs \ + mingw-w64 \ + && rm -rf /var/lib/apt/lists/* + +# Install powershell (universal package) so we can test x.ps1 on Linux +RUN curl -sL "https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/powershell_7.3.1-1.deb_amd64.deb" > powershell.deb && \ + dpkg -i powershell.deb && \ + rm -f powershell.deb + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +# We are disabling CI LLVM since this builder is intentionally using a host +# LLVM, rather than the typical src/llvm-project LLVM. +ENV NO_DOWNLOAD_CI_LLVM 1 + +# Using llvm-link-shared due to libffi issues -- see #34486 +ENV RUST_CONFIGURE_ARGS \ + --build=x86_64-unknown-linux-gnu \ + --llvm-root=/usr/lib/llvm-17 \ + --enable-llvm-link-shared \ + --set rust.thin-lto-import-instr-limit=10 + +COPY host-x86_64/x86_64-gnu-llvm-15/script.sh /tmp/ + +ENV SCRIPT /tmp/script.sh diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 5136aec9896f..2577682c57c6 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -463,6 +463,11 @@ jobs: - name: x86_64-gnu-distcheck <<: *job-linux-8c + - name: x86_64-gnu-llvm-17 + env: + RUST_BACKTRACE: 1 + <<: *job-linux-8c + - name: x86_64-gnu-llvm-16 env: RUST_BACKTRACE: 1 diff --git a/src/doc/rustdoc/src/write-documentation/what-to-include.md b/src/doc/rustdoc/src/write-documentation/what-to-include.md index 4bcae4d222c7..75d3b7dae61e 100644 --- a/src/doc/rustdoc/src/write-documentation/what-to-include.md +++ b/src/doc/rustdoc/src/write-documentation/what-to-include.md @@ -73,7 +73,7 @@ and your test suite, this example needs some additional code: ``````text /// Example /// ```rust -/// # main() -> Result<(), std::num::ParseIntError> { +/// # fn main() -> Result<(), std::num::ParseIntError> { /// let fortytwo = "42".parse::()?; /// println!("{} + 10 = {}", fortytwo, fortytwo+10); /// # Ok(()) diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py index 32b8d8e24c65..e851aa626344 100644 --- a/src/etc/gdb_providers.py +++ b/src/etc/gdb_providers.py @@ -18,70 +18,79 @@ def unwrap_unique_or_non_null(unique_or_nonnull): return ptr if ptr.type.code == gdb.TYPE_CODE_PTR else ptr[ptr.type.fields()[0]] -class EnumProvider: +# 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'): + printer_base = gdb.ValuePrinter +else: + printer_base = object + + +class EnumProvider(printer_base): def __init__(self, valobj): content = valobj[valobj.type.fields()[0]] fields = content.type.fields() - self.empty = len(fields) == 0 - if not self.empty: + self._empty = len(fields) == 0 + if not self._empty: if len(fields) == 1: discriminant = 0 else: discriminant = int(content[fields[0]]) + 1 - self.active_variant = content[fields[discriminant]] - self.name = fields[discriminant].name - self.full_name = "{}::{}".format(valobj.type.name, self.name) + self._active_variant = content[fields[discriminant]] + self._name = fields[discriminant].name + self._full_name = "{}::{}".format(valobj.type.name, self._name) else: - self.full_name = valobj.type.name + self._full_name = valobj.type.name def to_string(self): - return self.full_name + return self._full_name def children(self): - if not self.empty: - yield self.name, self.active_variant + if not self._empty: + yield self._name, self._active_variant -class StdStringProvider: +class StdStringProvider(printer_base): def __init__(self, valobj): - self.valobj = valobj + self._valobj = valobj vec = valobj["vec"] - self.length = int(vec["len"]) - self.data_ptr = unwrap_unique_or_non_null(vec["buf"]["ptr"]) + self._length = int(vec["len"]) + self._data_ptr = unwrap_unique_or_non_null(vec["buf"]["ptr"]) def to_string(self): - return self.data_ptr.lazy_string(encoding="utf-8", length=self.length) + return self._data_ptr.lazy_string(encoding="utf-8", length=self._length) @staticmethod def display_hint(): return "string" -class StdOsStringProvider: +class StdOsStringProvider(printer_base): def __init__(self, valobj): - self.valobj = valobj - buf = self.valobj["inner"]["inner"] + self._valobj = valobj + buf = self._valobj["inner"]["inner"] is_windows = "Wtf8Buf" in buf.type.name vec = buf[ZERO_FIELD] if is_windows else buf - self.length = int(vec["len"]) - self.data_ptr = unwrap_unique_or_non_null(vec["buf"]["ptr"]) + self._length = int(vec["len"]) + self._data_ptr = unwrap_unique_or_non_null(vec["buf"]["ptr"]) def to_string(self): - return self.data_ptr.lazy_string(encoding="utf-8", length=self.length) + return self._data_ptr.lazy_string(encoding="utf-8", length=self._length) def display_hint(self): return "string" -class StdStrProvider: +class StdStrProvider(printer_base): def __init__(self, valobj): - self.valobj = valobj - self.length = int(valobj["length"]) - self.data_ptr = valobj["data_ptr"] + self._valobj = valobj + self._length = int(valobj["length"]) + self._data_ptr = valobj["data_ptr"] def to_string(self): - return self.data_ptr.lazy_string(encoding="utf-8", length=self.length) + return self._data_ptr.lazy_string(encoding="utf-8", length=self._length) @staticmethod def display_hint(): @@ -103,36 +112,36 @@ def _enumerate_array_elements(element_ptrs): yield key, element -class StdSliceProvider: +class StdSliceProvider(printer_base): def __init__(self, valobj): - self.valobj = valobj - self.length = int(valobj["length"]) - self.data_ptr = valobj["data_ptr"] + self._valobj = valobj + self._length = int(valobj["length"]) + self._data_ptr = valobj["data_ptr"] def to_string(self): - return "{}(size={})".format(self.valobj.type, self.length) + return "{}(size={})".format(self._valobj.type, self._length) def children(self): return _enumerate_array_elements( - self.data_ptr + index for index in xrange(self.length) + self._data_ptr + index for index in xrange(self._length) ) @staticmethod def display_hint(): return "array" -class StdVecProvider: +class StdVecProvider(printer_base): def __init__(self, valobj): - self.valobj = valobj - self.length = int(valobj["len"]) - self.data_ptr = unwrap_unique_or_non_null(valobj["buf"]["ptr"]) + self._valobj = valobj + self._length = int(valobj["len"]) + self._data_ptr = unwrap_unique_or_non_null(valobj["buf"]["ptr"]) def to_string(self): - return "Vec(size={})".format(self.length) + return "Vec(size={})".format(self._length) def children(self): return _enumerate_array_elements( - self.data_ptr + index for index in xrange(self.length) + self._data_ptr + index for index in xrange(self._length) ) @staticmethod @@ -140,20 +149,20 @@ class StdVecProvider: return "array" -class StdVecDequeProvider: +class StdVecDequeProvider(printer_base): def __init__(self, valobj): - self.valobj = valobj - self.head = int(valobj["head"]) - self.size = int(valobj["len"]) - self.cap = int(valobj["buf"]["cap"]) - self.data_ptr = unwrap_unique_or_non_null(valobj["buf"]["ptr"]) + self._valobj = valobj + self._head = int(valobj["head"]) + self._size = int(valobj["len"]) + self._cap = int(valobj["buf"]["cap"]) + self._data_ptr = unwrap_unique_or_non_null(valobj["buf"]["ptr"]) def to_string(self): - return "VecDeque(size={})".format(self.size) + return "VecDeque(size={})".format(self._size) 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 @@ -161,81 +170,81 @@ class StdVecDequeProvider: return "array" -class StdRcProvider: +class StdRcProvider(printer_base): def __init__(self, valobj, is_atomic=False): - self.valobj = valobj - self.is_atomic = is_atomic - self.ptr = unwrap_unique_or_non_null(valobj["ptr"]) - self.value = self.ptr["data" if is_atomic else "value"] - self.strong = self.ptr["strong"]["v" if is_atomic else "value"]["value"] - self.weak = self.ptr["weak"]["v" if is_atomic else "value"]["value"] - 1 + self._valobj = valobj + self._is_atomic = is_atomic + self._ptr = unwrap_unique_or_non_null(valobj["ptr"]) + self._value = self._ptr["data" if is_atomic else "value"] + self._strong = self._ptr["strong"]["v" if is_atomic else "value"]["value"] + self._weak = self._ptr["weak"]["v" if is_atomic else "value"]["value"] - 1 def to_string(self): - if self.is_atomic: - return "Arc(strong={}, weak={})".format(int(self.strong), int(self.weak)) + if self._is_atomic: + return "Arc(strong={}, weak={})".format(int(self._strong), int(self._weak)) else: - return "Rc(strong={}, weak={})".format(int(self.strong), int(self.weak)) + return "Rc(strong={}, weak={})".format(int(self._strong), int(self._weak)) def children(self): - yield "value", self.value - yield "strong", self.strong - yield "weak", self.weak + yield "value", self._value + yield "strong", self._strong + yield "weak", self._weak -class StdCellProvider: +class StdCellProvider(printer_base): def __init__(self, valobj): - self.value = valobj["value"]["value"] + self._value = valobj["value"]["value"] def to_string(self): return "Cell" def children(self): - yield "value", self.value + yield "value", self._value -class StdRefProvider: +class StdRefProvider(printer_base): def __init__(self, valobj): - self.value = valobj["value"].dereference() - self.borrow = valobj["borrow"]["borrow"]["value"]["value"] + self._value = valobj["value"].dereference() + self._borrow = valobj["borrow"]["borrow"]["value"]["value"] def to_string(self): - borrow = int(self.borrow) + borrow = int(self._borrow) if borrow >= 0: return "Ref(borrow={})".format(borrow) else: return "Ref(borrow_mut={})".format(-borrow) def children(self): - yield "*value", self.value - yield "borrow", self.borrow + yield "*value", self._value + yield "borrow", self._borrow -class StdRefCellProvider: +class StdRefCellProvider(printer_base): def __init__(self, valobj): - self.value = valobj["value"]["value"] - self.borrow = valobj["borrow"]["value"]["value"] + self._value = valobj["value"]["value"] + self._borrow = valobj["borrow"]["value"]["value"] def to_string(self): - borrow = int(self.borrow) + borrow = int(self._borrow) if borrow >= 0: return "RefCell(borrow={})".format(borrow) else: return "RefCell(borrow_mut={})".format(-borrow) def children(self): - yield "value", self.value - yield "borrow", self.borrow + yield "value", self._value + yield "borrow", self._borrow -class StdNonZeroNumberProvider: +class StdNonZeroNumberProvider(printer_base): def __init__(self, valobj): fields = valobj.type.fields() assert len(fields) == 1 field = list(fields)[0] - self.value = str(valobj[field.name]) + self._value = str(valobj[field.name]) def to_string(self): - return self.value + return self._value # Yields children (in a provider's sense of the word) for a BTreeMap. @@ -280,15 +289,15 @@ def children_of_btree_map(map): yield child -class StdBTreeSetProvider: +class StdBTreeSetProvider(printer_base): def __init__(self, valobj): - self.valobj = valobj + self._valobj = valobj def to_string(self): - return "BTreeSet(size={})".format(self.valobj["map"]["length"]) + return "BTreeSet(size={})".format(self._valobj["map"]["length"]) def children(self): - inner_map = self.valobj["map"] + inner_map = self._valobj["map"] for i, (child, _) in enumerate(children_of_btree_map(inner_map)): yield "[{}]".format(i), child @@ -297,15 +306,15 @@ class StdBTreeSetProvider: return "array" -class StdBTreeMapProvider: +class StdBTreeMapProvider(printer_base): def __init__(self, valobj): - self.valobj = valobj + self._valobj = valobj def to_string(self): - return "BTreeMap(size={})".format(self.valobj["length"]) + return "BTreeMap(size={})".format(self._valobj["length"]) def children(self): - for i, (key, val) in enumerate(children_of_btree_map(self.valobj)): + for i, (key, val) in enumerate(children_of_btree_map(self._valobj)): yield "key{}".format(i), key yield "val{}".format(i), val @@ -315,124 +324,124 @@ class StdBTreeMapProvider: # BACKCOMPAT: rust 1.35 -class StdOldHashMapProvider: +class StdOldHashMapProvider(printer_base): def __init__(self, valobj, show_values=True): - self.valobj = valobj - self.show_values = show_values + self._valobj = valobj + self._show_values = show_values - self.table = self.valobj["table"] - self.size = int(self.table["size"]) - 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.data_ptr = self.hashes[ZERO_FIELD]["pointer"] + self._table = self._valobj["table"] + self._size = int(self._table["size"]) + 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._data_ptr = self._hashes[ZERO_FIELD]["pointer"] - self.capacity_mask = int(self.table["capacity_mask"]) - self.capacity = (self.capacity_mask + 1) % self.modulo + self._capacity_mask = int(self._table["capacity_mask"]) + self._capacity = (self._capacity_mask + 1) % self._modulo - marker = self.table["marker"].type - self.pair_type = marker.template_argument(0) - self.pair_type_size = self.pair_type.sizeof + marker = self._table["marker"].type + self._pair_type = marker.template_argument(0) + self._pair_type_size = self._pair_type.sizeof - self.valid_indices = [] - for idx in range(self.capacity): - data_ptr = self.data_ptr.cast(self.hash_uint_type.pointer()) + self._valid_indices = [] + for idx in range(self._capacity): + data_ptr = self._data_ptr.cast(self._hash_uint_type.pointer()) address = data_ptr + idx hash_uint = address.dereference() hash_ptr = hash_uint[ZERO_FIELD]["pointer"] if int(hash_ptr) != 0: - self.valid_indices.append(idx) + self._valid_indices.append(idx) def to_string(self): - if self.show_values: - return "HashMap(size={})".format(self.size) + if self._show_values: + return "HashMap(size={})".format(self._size) else: - return "HashSet(size={})".format(self.size) + return "HashSet(size={})".format(self._size) def children(self): - start = int(self.data_ptr) & ~1 + start = int(self._data_ptr) & ~1 - 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 + 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 pairs_offset = hashes + len_rounded_up - pairs_start = gdb.Value(start + pairs_offset).cast(self.pair_type.pointer()) + pairs_start = gdb.Value(start + pairs_offset).cast(self._pair_type.pointer()) - for index in range(self.size): - table_index = self.valid_indices[index] - idx = table_index & self.capacity_mask + for index in range(self._size): + table_index = self._valid_indices[index] + idx = table_index & self._capacity_mask element = (pairs_start + idx).dereference() - if self.show_values: + if self._show_values: yield "key{}".format(index), element[ZERO_FIELD] yield "val{}".format(index), element[FIRST_FIELD] else: yield "[{}]".format(index), element[ZERO_FIELD] def display_hint(self): - return "map" if self.show_values else "array" + return "map" if self._show_values else "array" -class StdHashMapProvider: +class StdHashMapProvider(printer_base): def __init__(self, valobj, show_values=True): - self.valobj = valobj - self.show_values = show_values + self._valobj = valobj + self._show_values = show_values - table = self.table() + table = self._table() table_inner = table["table"] capacity = int(table_inner["bucket_mask"]) + 1 ctrl = table_inner["ctrl"]["pointer"] - self.size = int(table_inner["items"]) - self.pair_type = table.type.template_argument(0).strip_typedefs() + self._size = int(table_inner["items"]) + self._pair_type = table.type.template_argument(0).strip_typedefs() - self.new_layout = not table_inner.type.has_key("data") - if self.new_layout: - self.data_ptr = ctrl.cast(self.pair_type.pointer()) + self._new_layout = not table_inner.type.has_key("data") + if self._new_layout: + self._data_ptr = ctrl.cast(self._pair_type.pointer()) else: - self.data_ptr = table_inner["data"]["pointer"] + self._data_ptr = table_inner["data"]["pointer"] - self.valid_indices = [] + self._valid_indices = [] for idx in range(capacity): address = ctrl + idx value = address.dereference() is_presented = value & 128 == 0 if is_presented: - self.valid_indices.append(idx) + self._valid_indices.append(idx) - def table(self): - if self.show_values: - hashbrown_hashmap = self.valobj["base"] - elif self.valobj.type.fields()[0].name == "map": + def _table(self): + if self._show_values: + hashbrown_hashmap = self._valobj["base"] + elif self._valobj.type.fields()[0].name == "map": # BACKCOMPAT: rust 1.47 # HashSet wraps std::collections::HashMap, which wraps hashbrown::HashMap - hashbrown_hashmap = self.valobj["map"]["base"] + hashbrown_hashmap = self._valobj["map"]["base"] else: # HashSet wraps hashbrown::HashSet, which wraps hashbrown::HashMap - hashbrown_hashmap = self.valobj["base"]["map"] + hashbrown_hashmap = self._valobj["base"]["map"] return hashbrown_hashmap["table"] def to_string(self): - if self.show_values: - return "HashMap(size={})".format(self.size) + if self._show_values: + return "HashMap(size={})".format(self._size) else: - return "HashSet(size={})".format(self.size) + return "HashSet(size={})".format(self._size) def children(self): - pairs_start = self.data_ptr + pairs_start = self._data_ptr - for index in range(self.size): - idx = self.valid_indices[index] - if self.new_layout: + for index in range(self._size): + idx = self._valid_indices[index] + if self._new_layout: idx = -(idx + 1) element = (pairs_start + idx).dereference() - if self.show_values: + if self._show_values: yield "key{}".format(index), element[ZERO_FIELD] yield "val{}".format(index), element[FIRST_FIELD] else: yield "[{}]".format(index), element[ZERO_FIELD] def display_hint(self): - return "map" if self.show_values else "array" + return "map" if self._show_values else "array" diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index eb18ecf662c1..89796761126d 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -641,13 +641,13 @@ fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant { clean::simplify::move_bounds_to_generic_parameters(&mut generics); clean::Constant { - type_: clean_middle_ty( + type_: Box::new(clean_middle_ty( ty::Binder::dummy(cx.tcx.type_of(def_id).instantiate_identity()), cx, Some(def_id), None, - ), - generics: Box::new(generics), + )), + generics, kind: clean::ConstantKind::Extern { def_id }, } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7becc156142d..125b1fecf18f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -259,13 +259,13 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg, cx: &mut DocContext<'tcx>) -> Constant { let def_id = cx.tcx.hir().body_owner_def_id(constant.value.body).to_def_id(); Constant { - type_: clean_middle_ty( + type_: Box::new(clean_middle_ty( ty::Binder::dummy(cx.tcx.type_of(def_id).instantiate_identity()), cx, Some(def_id), None, - ), - generics: Box::new(Generics::default()), + )), + generics: Generics::default(), kind: ConstantKind::Anonymous { body: constant.value.body }, } } @@ -276,8 +276,8 @@ pub(crate) fn clean_middle_const<'tcx>( ) -> Constant { // FIXME: instead of storing the stringified expression, store `self` directly instead. Constant { - type_: clean_middle_ty(constant.map_bound(|c| c.ty()), cx, None, None), - generics: Box::new(Generics::default()), + type_: Box::new(clean_middle_ty(constant.map_bound(|c| c.ty()), cx, None, None)), + generics: Generics::default(), kind: ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() }, } } @@ -1216,14 +1216,14 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext hir::TraitItemKind::Const(ty, Some(default)) => { let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)); AssocConstItem( - Box::new(generics), - clean_ty(ty, cx), + generics, + Box::new(clean_ty(ty, cx)), ConstantKind::Local { def_id: local_did, body: default }, ) } hir::TraitItemKind::Const(ty, None) => { let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)); - TyAssocConstItem(Box::new(generics), clean_ty(ty, cx)) + TyAssocConstItem(generics, Box::new(clean_ty(ty, cx))) } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Body(body)); @@ -1272,7 +1272,7 @@ pub(crate) fn clean_impl_item<'tcx>( hir::ImplItemKind::Const(ty, expr) => { let generics = clean_generics(impl_.generics, cx); let default = ConstantKind::Local { def_id: local_did, body: expr }; - AssocConstItem(Box::new(generics), clean_ty(ty, cx), default) + AssocConstItem(generics, Box::new(clean_ty(ty, cx)), default) } hir::ImplItemKind::Fn(ref sig, body) => { let m = clean_function(cx, sig, impl_.generics, FunctionArgs::Body(body)); @@ -1311,18 +1311,18 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( let tcx = cx.tcx; let kind = match assoc_item.kind { ty::AssocKind::Const => { - let ty = clean_middle_ty( + let ty = Box::new(clean_middle_ty( ty::Binder::dummy(tcx.type_of(assoc_item.def_id).instantiate_identity()), cx, Some(assoc_item.def_id), None, - ); + )); - let mut generics = Box::new(clean_ty_generics( + let mut generics = clean_ty_generics( cx, tcx.generics_of(assoc_item.def_id), tcx.explicit_predicates_of(assoc_item.def_id), - )); + ); simplify::move_bounds_to_generic_parameters(&mut generics); let provided = match assoc_item.container { @@ -2718,8 +2718,8 @@ fn clean_maybe_renamed_item<'tcx>( StaticItem(Static { type_: clean_ty(ty, cx), mutability, expr: Some(body_id) }) } ItemKind::Const(ty, generics, body_id) => ConstantItem(Constant { - type_: clean_ty(ty, cx), - generics: Box::new(clean_generics(generics, cx)), + type_: Box::new(clean_ty(ty, cx)), + generics: clean_generics(generics, cx), kind: ConstantKind::Local { body: body_id, def_id }, }), ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 2a54266676d0..6a7410144fd5 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -852,9 +852,9 @@ pub(crate) enum ItemKind { ProcMacroItem(ProcMacro), PrimitiveItem(PrimitiveType), /// A required associated constant in a trait declaration. - TyAssocConstItem(Box, Type), + TyAssocConstItem(Generics, Box), /// An associated constant in a trait impl or a provided one in a trait declaration. - AssocConstItem(Box, Type, ConstantKind), + AssocConstItem(Generics, Box, ConstantKind), /// A required associated type in a trait declaration. /// /// The bounds may be non-empty if there is a `where` clause. @@ -2282,8 +2282,8 @@ pub(crate) struct Static { #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub(crate) struct Constant { - pub(crate) type_: Type, - pub(crate) generics: Box, + pub(crate) type_: Box, + pub(crate) generics: Generics, pub(crate) kind: ConstantKind, } @@ -2524,8 +2524,7 @@ mod size_asserts { static_assert_size!(GenericParamDef, 56); static_assert_size!(Generics, 16); static_assert_size!(Item, 56); - // FIXME(generic_const_items): Further reduce the size. - static_assert_size!(ItemKind, 72); + static_assert_size!(ItemKind, 56); static_assert_size!(PathSegment, 40); static_assert_size!(Type, 32); // tidy-alphabetical-end diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index aa3f7184b4eb..29fd880af50e 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -847,7 +847,7 @@ fn resolved_path<'cx>( fn primitive_link( f: &mut fmt::Formatter<'_>, prim: clean::PrimitiveType, - name: &str, + name: fmt::Arguments<'_>, cx: &Context<'_>, ) -> fmt::Result { primitive_link_fragment(f, prim, name, "", cx) @@ -856,7 +856,7 @@ fn primitive_link( fn primitive_link_fragment( f: &mut fmt::Formatter<'_>, prim: clean::PrimitiveType, - name: &str, + name: fmt::Arguments<'_>, fragment: &str, cx: &Context<'_>, ) -> fmt::Result { @@ -907,7 +907,7 @@ fn primitive_link_fragment( None => {} } } - f.write_str(name)?; + std::fmt::Display::fmt(&name, f)?; if needs_termination { write!(f, "")?; } @@ -977,9 +977,11 @@ fn fmt_type<'cx>( } clean::Infer => write!(f, "_"), clean::Primitive(clean::PrimitiveType::Never) => { - primitive_link(f, PrimitiveType::Never, "!", cx) + primitive_link(f, PrimitiveType::Never, format_args!("!"), cx) + } + clean::Primitive(prim) => { + primitive_link(f, prim, format_args!("{}", prim.as_sym().as_str()), cx) } - clean::Primitive(prim) => primitive_link(f, prim, prim.as_sym().as_str(), cx), clean::BareFunction(ref decl) => { if f.alternate() { write!( @@ -998,16 +1000,16 @@ fn fmt_type<'cx>( decl.unsafety.print_with_space(), print_abi_with_space(decl.abi) )?; - primitive_link(f, PrimitiveType::Fn, "fn", cx)?; + primitive_link(f, PrimitiveType::Fn, format_args!("fn"), cx)?; write!(f, "{}", decl.decl.print(cx)) } } clean::Tuple(ref typs) => { match &typs[..] { - &[] => primitive_link(f, PrimitiveType::Unit, "()", cx), + &[] => primitive_link(f, PrimitiveType::Unit, format_args!("()"), cx), [one] => { if let clean::Generic(name) = one { - primitive_link(f, PrimitiveType::Tuple, &format!("({name},)"), cx) + primitive_link(f, PrimitiveType::Tuple, format_args!("({name},)"), cx) } else { write!(f, "(")?; // Carry `f.alternate()` into this display w/o branching manually. @@ -1028,7 +1030,10 @@ fn fmt_type<'cx>( primitive_link( f, PrimitiveType::Tuple, - &format!("({})", generic_names.iter().map(|s| s.as_str()).join(", ")), + format_args!( + "({})", + generic_names.iter().map(|s| s.as_str()).join(", ") + ), cx, ) } else { @@ -1047,7 +1052,7 @@ fn fmt_type<'cx>( } clean::Slice(ref t) => match **t { clean::Generic(name) => { - primitive_link(f, PrimitiveType::Slice, &format!("[{name}]"), cx) + primitive_link(f, PrimitiveType::Slice, format_args!("[{name}]"), cx) } _ => { write!(f, "[")?; @@ -1059,7 +1064,7 @@ fn fmt_type<'cx>( clean::Generic(name) if !f.alternate() => primitive_link( f, PrimitiveType::Array, - &format!("[{name}; {n}]", n = Escape(n)), + format_args!("[{name}; {n}]", n = Escape(n)), cx, ), _ => { @@ -1069,7 +1074,12 @@ fn fmt_type<'cx>( write!(f, "; {n}")?; } else { write!(f, "; ")?; - primitive_link(f, PrimitiveType::Array, &format!("{n}", n = Escape(n)), cx)?; + primitive_link( + f, + PrimitiveType::Array, + format_args!("{n}", n = Escape(n)), + cx, + )?; } write!(f, "]") } @@ -1081,22 +1091,32 @@ fn fmt_type<'cx>( }; if matches!(**t, clean::Generic(_)) || t.is_assoc_ty() { - let text = if f.alternate() { - format!("*{m} {ty:#}", ty = t.print(cx)) + let ty = t.print(cx); + if f.alternate() { + primitive_link( + f, + clean::PrimitiveType::RawPointer, + format_args!("*{m} {ty:#}"), + cx, + ) } else { - format!("*{m} {ty}", ty = t.print(cx)) - }; - primitive_link(f, clean::PrimitiveType::RawPointer, &text, cx) + primitive_link( + f, + clean::PrimitiveType::RawPointer, + format_args!("*{m} {ty}"), + cx, + ) + } } else { - primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{m} "), cx)?; + primitive_link(f, clean::PrimitiveType::RawPointer, format_args!("*{m} "), cx)?; fmt::Display::fmt(&t.print(cx), f) } } clean::BorrowedRef { lifetime: ref l, mutability, type_: ref ty } => { - let lt = match l { - Some(l) => format!("{} ", l.print()), - _ => String::new(), - }; + let lt = display_fn(|f| match l { + Some(l) => write!(f, "{} ", l.print()), + _ => Ok(()), + }); let m = mutability.print_with_space(); let amp = if f.alternate() { "&" } else { "&" }; @@ -1104,7 +1124,7 @@ fn fmt_type<'cx>( return primitive_link( f, PrimitiveType::Reference, - &format!("{amp}{lt}{m}{name}"), + format_args!("{amp}{lt}{m}{name}"), cx, ); } @@ -1254,7 +1274,7 @@ impl clean::Impl { { // Hardcoded anchor library/core/src/primitive_docs.rs // Link should match `# Trait implementations` - primitive_link_fragment(f, PrimitiveType::Tuple, &format!("({name}₁, {name}₂, …, {name}ₙ)"), "#trait-implementations-1", cx)?; + primitive_link_fragment(f, PrimitiveType::Tuple, format_args!("({name}₁, {name}₂, …, {name}ₙ)"), "#trait-implementations-1", cx)?; } else if let clean::BareFunction(bare_fn) = &self.for_ && let [clean::Argument { type_: clean::Type::Generic(name), .. }] = &bare_fn.decl.inputs.values[..] && (self.kind.is_fake_variadic() || self.kind.is_auto()) @@ -1281,7 +1301,7 @@ impl clean::Impl { } else { "" }; - primitive_link_fragment(f, PrimitiveType::Tuple, &format!("fn ({name}₁, {name}₂, …, {name}ₙ{ellipsis})"), "#trait-implementations-1", cx)?; + primitive_link_fragment(f, PrimitiveType::Tuple, format_args!("fn ({name}₁, {name}₂, …, {name}ₙ{ellipsis})"), "#trait-implementations-1", cx)?; // Write output. if !bare_fn.decl.output.is_unit() { write!(f, " -> ")?; @@ -1665,7 +1685,12 @@ impl clean::ImportSource { } let name = self.path.last(); if let hir::def::Res::PrimTy(p) = self.path.res { - primitive_link(f, PrimitiveType::from(p), name.as_str(), cx)?; + primitive_link( + f, + PrimitiveType::from(p), + format_args!("{}", name.as_str()), + cx, + )?; } else { f.write_str(name.as_str())?; } diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 17e2172a2706..563e0cffdddb 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -177,7 +177,7 @@ impl FromWithTcx for Constant { let expr = constant.expr(tcx); let value = constant.value(tcx); let is_literal = constant.is_literal(tcx); - Constant { type_: constant.type_.into_tcx(tcx), expr, value, is_literal } + Constant { type_: (*constant.type_).into_tcx(tcx), expr, value, is_literal } } } @@ -325,11 +325,11 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { } // FIXME(generic_const_items): Add support for generic associated consts. TyAssocConstItem(_generics, ty) => { - ItemEnum::AssocConst { type_: ty.into_tcx(tcx), default: None } + ItemEnum::AssocConst { type_: (*ty).into_tcx(tcx), default: None } } // FIXME(generic_const_items): Add support for generic associated consts. AssocConstItem(_generics, ty, default) => { - ItemEnum::AssocConst { type_: ty.into_tcx(tcx), default: Some(default.expr(tcx)) } + ItemEnum::AssocConst { type_: (*ty).into_tcx(tcx), default: Some(default.expr(tcx)) } } TyAssocTypeItem(g, b) => ItemEnum::AssocType { generics: g.into_tcx(tcx), diff --git a/src/tools/cargo b/src/tools/cargo index 8eb8acbb116e..d2f6a048529e 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 8eb8acbb116e7923ea2ce33a50109933ed5ab375 +Subproject commit d2f6a048529eb8e9ebc55d793abd63456c98fac2 diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 0335ad3c1d87..9e9f2bad7c34 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -9e3f784eb2c7c847b6c3578b373c0e0bc9233ca3 +62fae2305e5f3a959bd6ad6c20608c118e93648a diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs index b63b0bdff121..4232cd396c95 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs @@ -661,13 +661,11 @@ impl<'tcx> Tree { for (perms_range, perms) in self.rperms.iter_mut_all() { let idx = self.tag_mapping.get(&tag).unwrap(); // Only visit initialized permissions - if let Some(p) = perms.get(idx) && p.initialized { - TreeVisitor { - nodes: &mut self.nodes, - tag_mapping: &self.tag_mapping, - perms, - } - .traverse_nonchildren( + if let Some(p) = perms.get(idx) + && p.initialized + { + TreeVisitor { nodes: &mut self.nodes, tag_mapping: &self.tag_mapping, perms } + .traverse_nonchildren( tag, |args| node_app(perms_range.clone(), args), |args| err_handler(perms_range.clone(), args), diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index bec2972c50d6..e49d62177c55 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -563,6 +563,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { let old = this.allow_data_races_mut(|this| this.read_immediate(place))?; let lt = this.wrapping_binary_op(mir::BinOp::Lt, &old, &rhs)?.to_scalar().to_bool()?; + #[rustfmt::skip] // rustfmt makes this unreadable let new_val = if min { if lt { &old } else { &rhs } } else { diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index 759a412c16a2..4ad44adff04c 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -351,7 +351,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; this.read_target_isize(hModule)?; let name = this.read_c_str(this.read_pointer(lpProcName)?)?; - if let Ok(name) = str::from_utf8(name) && is_dyn_sym(name) { + if let Ok(name) = str::from_utf8(name) + && is_dyn_sym(name) + { let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str(name))); this.write_pointer(ptr, dest)?; } else { diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs index 9cdff84676ee..f9ff1a0a4860 100644 --- a/src/tools/opt-dist/src/main.rs +++ b/src/tools/opt-dist/src/main.rs @@ -408,8 +408,8 @@ fn download_rustc_perf(env: &Environment) -> anyhow::Result<()> { // FIXME: add some mechanism for synchronization of this commit SHA with // Linux (which builds rustc-perf in a Dockerfile) - // rustc-perf version from 2023-05-30 - const PERF_COMMIT: &str = "8b2ac3042e1ff2c0074455a0a3618adef97156b1"; + // rustc-perf version from 2023-10-22 + const PERF_COMMIT: &str = "4f313add609f43e928e98132358e8426ed3969ae"; let url = format!("https://ci-mirrors.rust-lang.org/rustc/rustc-perf-{PERF_COMMIT}.zip"); let client = reqwest::blocking::Client::builder() diff --git a/src/tools/opt-dist/src/tests.rs b/src/tools/opt-dist/src/tests.rs index 8000c9e7fddc..3c33cfe985da 100644 --- a/src/tools/opt-dist/src/tests.rs +++ b/src/tools/opt-dist/src/tests.rs @@ -24,11 +24,10 @@ pub fn run_tests(env: &Environment) -> anyhow::Result<()> { let host_triple = env.host_triple(); let version = find_dist_version(&dist_dir)?; - // Extract rustc, libstd, cargo and src archives to create the optimized sysroot + // Extract rustc, libstd and src archives to create the optimized sysroot let rustc_dir = extract_dist_dir(&format!("rustc-{version}-{host_triple}"))?.join("rustc"); let libstd_dir = extract_dist_dir(&format!("rust-std-{version}-{host_triple}"))? .join(format!("rust-std-{host_triple}")); - let cargo_dir = extract_dist_dir(&format!("cargo-{version}-{host_triple}"))?.join("cargo"); let extracted_src_dir = extract_dist_dir(&format!("rust-src-{version}"))?.join("rust-src"); // We need to manually copy libstd to the extracted rustc sysroot @@ -47,8 +46,6 @@ pub fn run_tests(env: &Environment) -> anyhow::Result<()> { let rustc_path = rustc_dir.join("bin").join(format!("rustc{}", executable_extension())); assert!(rustc_path.is_file()); - let cargo_path = cargo_dir.join("bin").join(format!("cargo{}", executable_extension())); - assert!(cargo_path.is_file()); // Specify path to a LLVM config so that LLVM is not rebuilt. // It doesn't really matter which LLVM config we choose, because no sysroot will be compiled. @@ -65,13 +62,11 @@ change-id = 115898 [build] rustc = "{rustc}" -cargo = "{cargo}" [target.{host_triple}] llvm-config = "{llvm_config}" "#, rustc = rustc_path.to_string().replace('\\', "/"), - cargo = cargo_path.to_string().replace('\\', "/"), llvm_config = llvm_config.to_string().replace('\\', "/") ); log::info!("Using following `config.toml` for running tests:\n{config_content}"); @@ -84,6 +79,8 @@ llvm-config = "{llvm_config}" env.python_binary(), x_py.as_str(), "test", + "--build", + env.host_triple(), "--stage", "0", "tests/assembly", diff --git a/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.rs b/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.rs new file mode 100644 index 000000000000..ced4434a7a7c --- /dev/null +++ b/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.rs @@ -0,0 +1,10 @@ +// check-fail +// edition:2021 + +// test for issue-114912 - debug ice: attempted to add with overflow + +async fn main() { + //~^ ERROR `main` function is not allowed to be `async` + [0usize; 0xffff_ffff_ffff_ffff].await; + //~^ ERROR `[usize; usize::MAX]` is not a future +} diff --git a/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr b/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr new file mode 100644 index 000000000000..8c9d06c79ca4 --- /dev/null +++ b/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr @@ -0,0 +1,23 @@ +error[E0277]: `[usize; usize::MAX]` is not a future + --> $DIR/debug-ice-attempted-to-add-with-overflow.rs:8:37 + | +LL | [0usize; 0xffff_ffff_ffff_ffff].await; + | -^^^^^ + | || + | |`[usize; usize::MAX]` is not a future + | help: remove the `.await` + | + = help: the trait `Future` is not implemented for `[usize; usize::MAX]` + = note: [usize; usize::MAX] must be a future or must implement `IntoFuture` to be awaited + = note: required for `[usize; usize::MAX]` to implement `IntoFuture` + +error[E0752]: `main` function is not allowed to be `async` + --> $DIR/debug-ice-attempted-to-add-with-overflow.rs:6:1 + | +LL | async fn main() { + | ^^^^^^^^^^^^^^^ `main` function is not allowed to be `async` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0752. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/did_you_mean/issue-105225-named-args.rs b/tests/ui/did_you_mean/issue-105225-named-args.rs new file mode 100644 index 000000000000..38e817765769 --- /dev/null +++ b/tests/ui/did_you_mean/issue-105225-named-args.rs @@ -0,0 +1,10 @@ +fn main() { + let x = "x"; + let y = "y"; + + println!("{x}", x, x = y); + //~^ ERROR: redundant argument + + println!("{x}", x = y, x = y); + //~^ ERROR: duplicate argument named `x` +} diff --git a/tests/ui/did_you_mean/issue-105225-named-args.stderr b/tests/ui/did_you_mean/issue-105225-named-args.stderr new file mode 100644 index 000000000000..72204102ef6c --- /dev/null +++ b/tests/ui/did_you_mean/issue-105225-named-args.stderr @@ -0,0 +1,22 @@ +error: redundant argument + --> $DIR/issue-105225-named-args.rs:5:21 + | +LL | println!("{x}", x, x = y); + | ^ + | +note: the formatting specifier is referencing the binding already + --> $DIR/issue-105225-named-args.rs:5:16 + | +LL | println!("{x}", x, x = y); + | ^ + +error: duplicate argument named `x` + --> $DIR/issue-105225-named-args.rs:8:28 + | +LL | println!("{x}", x = y, x = y); + | - ^ duplicate argument + | | + | previously here + +error: aborting due to 2 previous errors + diff --git a/tests/ui/did_you_mean/issue-105225.fixed b/tests/ui/did_you_mean/issue-105225.fixed new file mode 100644 index 000000000000..f756be615a1b --- /dev/null +++ b/tests/ui/did_you_mean/issue-105225.fixed @@ -0,0 +1,21 @@ +// run-rustfix + +fn main() { + let x = "x"; + let y = "y"; + + println!("{x}", ); + //~^ ERROR: redundant argument + + println!("{x} {}", x, ); + //~^ ERROR: redundant argument + + println!("{} {x}", x, ); + //~^ ERROR: redundant argument + + println!("{x} {y}", ); + //~^ ERROR: redundant arguments + + println!("{} {} {x} {y} {}", x, x, x, ); + //~^ ERROR: redundant arguments +} diff --git a/tests/ui/did_you_mean/issue-105225.rs b/tests/ui/did_you_mean/issue-105225.rs new file mode 100644 index 000000000000..91cdf0eb28f6 --- /dev/null +++ b/tests/ui/did_you_mean/issue-105225.rs @@ -0,0 +1,21 @@ +// run-rustfix + +fn main() { + let x = "x"; + let y = "y"; + + println!("{x}", x); + //~^ ERROR: redundant argument + + println!("{x} {}", x, x); + //~^ ERROR: redundant argument + + println!("{} {x}", x, x); + //~^ ERROR: redundant argument + + println!("{x} {y}", x, y); + //~^ ERROR: redundant arguments + + println!("{} {} {x} {y} {}", x, x, x, y, y); + //~^ ERROR: redundant arguments +} diff --git a/tests/ui/did_you_mean/issue-105225.stderr b/tests/ui/did_you_mean/issue-105225.stderr new file mode 100644 index 000000000000..5fb46222bee5 --- /dev/null +++ b/tests/ui/did_you_mean/issue-105225.stderr @@ -0,0 +1,72 @@ +error: redundant argument + --> $DIR/issue-105225.rs:7:21 + | +LL | println!("{x}", x); + | ^ help: this can be removed + | +note: the formatting specifier is referencing the binding already + --> $DIR/issue-105225.rs:7:16 + | +LL | println!("{x}", x); + | ^ + +error: redundant argument + --> $DIR/issue-105225.rs:10:27 + | +LL | println!("{x} {}", x, x); + | ^ help: this can be removed + | +note: the formatting specifier is referencing the binding already + --> $DIR/issue-105225.rs:10:16 + | +LL | println!("{x} {}", x, x); + | ^ + +error: redundant argument + --> $DIR/issue-105225.rs:13:27 + | +LL | println!("{} {x}", x, x); + | ^ help: this can be removed + | +note: the formatting specifier is referencing the binding already + --> $DIR/issue-105225.rs:13:19 + | +LL | println!("{} {x}", x, x); + | ^ + +error: redundant arguments + --> $DIR/issue-105225.rs:16:25 + | +LL | println!("{x} {y}", x, y); + | ^ ^ + | +note: the formatting specifiers are referencing the bindings already + --> $DIR/issue-105225.rs:16:16 + | +LL | println!("{x} {y}", x, y); + | ^ ^ +help: this can be removed + | +LL - println!("{x} {y}", x, y); +LL + println!("{x} {y}", ); + | + +error: redundant arguments + --> $DIR/issue-105225.rs:19:43 + | +LL | println!("{} {} {x} {y} {}", x, x, x, y, y); + | ^ ^ + | +note: the formatting specifiers are referencing the bindings already + --> $DIR/issue-105225.rs:19:26 + | +LL | println!("{} {} {x} {y} {}", x, x, x, y, y); + | ^ +help: this can be removed + | +LL - println!("{} {} {x} {y} {}", x, x, x, y, y); +LL + println!("{} {} {x} {y} {}", x, x, x, ); + | + +error: aborting due to 5 previous errors + diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs index ecfeb3f9b98b..e0a6051a81fa 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs @@ -251,3 +251,10 @@ fn main() { pub fn takes_non_exhaustive(_: NonExhaustiveEnum) { let _closure = |_: NonExhaustiveEnum| {}; } + +// ICE #117033 +enum Void {} +#[deny(non_exhaustive_omitted_patterns)] +pub fn void(v: Void) -> ! { + match v {} +}