Auto merge of #3136 - rust-lang:rustup-2023-10-23, r=RalfJung
Automatic Rustup
This commit is contained in:
commit
d32b1583df
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@ -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
|
||||
|
12
Cargo.lock
12
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",
|
||||
]
|
||||
|
@ -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
|
||||
|
@ -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<FormatRedundantArgsSugg>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(builtin_macros_suggestion, applicability = "machine-applicable")]
|
||||
pub(crate) struct FormatRedundantArgsSugg {
|
||||
#[suggestion_part(code = "")]
|
||||
pub(crate) spans: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_test_case_non_item)]
|
||||
pub(crate) struct TestCaseNonItem {
|
||||
|
@ -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<usize>,
|
||||
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::<Vec<_>>();
|
||||
|
||||
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<DiagnosticBuilder<'a, ErrorGuaranteed>> {
|
||||
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::<Vec<_>>();
|
||||
|
||||
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
|
||||
|
@ -884,6 +884,9 @@ fn collect_nonexhaustive_missing_variants<'p, 'tcx>(
|
||||
cx: &MatchCheckCtxt<'p, 'tcx>,
|
||||
column: &[&DeconstructedPat<'p, 'tcx>],
|
||||
) -> Vec<WitnessPat<'tcx>> {
|
||||
if column.is_empty() {
|
||||
return Vec::new();
|
||||
}
|
||||
let ty = column[0].ty();
|
||||
let pcx = &PatCtxt { cx, ty, span: DUMMY_SP, is_top_level: false };
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 && \
|
||||
|
@ -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 \
|
||||
|
50
src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile
Normal file
50
src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile
Normal file
@ -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
|
@ -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
|
||||
|
@ -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::<u32>()?;
|
||||
/// println!("{} + 10 = {}", fortytwo, fortytwo+10);
|
||||
/// # Ok(())
|
||||
|
@ -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"
|
||||
|
@ -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 },
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -852,9 +852,9 @@ pub(crate) enum ItemKind {
|
||||
ProcMacroItem(ProcMacro),
|
||||
PrimitiveItem(PrimitiveType),
|
||||
/// A required associated constant in a trait declaration.
|
||||
TyAssocConstItem(Box<Generics>, Type),
|
||||
TyAssocConstItem(Generics, Box<Type>),
|
||||
/// An associated constant in a trait impl or a provided one in a trait declaration.
|
||||
AssocConstItem(Box<Generics>, Type, ConstantKind),
|
||||
AssocConstItem(Generics, Box<Type>, 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<Generics>,
|
||||
pub(crate) type_: Box<Type>,
|
||||
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
|
||||
|
@ -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, "</a>")?;
|
||||
}
|
||||
@ -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())?;
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ impl FromWithTcx<clean::Constant> 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),
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 8eb8acbb116e7923ea2ce33a50109933ed5ab375
|
||||
Subproject commit d2f6a048529eb8e9ebc55d793abd63456c98fac2
|
@ -1 +1 @@
|
||||
9e3f784eb2c7c847b6c3578b373c0e0bc9233ca3
|
||||
62fae2305e5f3a959bd6ad6c20608c118e93648a
|
||||
|
@ -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),
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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()
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
}
|
@ -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`.
|
10
tests/ui/did_you_mean/issue-105225-named-args.rs
Normal file
10
tests/ui/did_you_mean/issue-105225-named-args.rs
Normal file
@ -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`
|
||||
}
|
22
tests/ui/did_you_mean/issue-105225-named-args.stderr
Normal file
22
tests/ui/did_you_mean/issue-105225-named-args.stderr
Normal file
@ -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
|
||||
|
21
tests/ui/did_you_mean/issue-105225.fixed
Normal file
21
tests/ui/did_you_mean/issue-105225.fixed
Normal file
@ -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
|
||||
}
|
21
tests/ui/did_you_mean/issue-105225.rs
Normal file
21
tests/ui/did_you_mean/issue-105225.rs
Normal file
@ -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
|
||||
}
|
72
tests/ui/did_you_mean/issue-105225.stderr
Normal file
72
tests/ui/did_you_mean/issue-105225.stderr
Normal file
@ -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
|
||||
|
@ -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 {}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user