Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions bootstrap.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,11 @@
# which is also used in places like debuginfo `DW_AT_producer`. This may be useful for
# supplementary build information, like distro-specific package versions.
#
# IMPORTANT: Changing this value changes crate IDs and symbol name mangling, making
# compiled artifacts incompatible. PGO profiles cannot be reused across different
# descriptions, and incremental compilation caches are invalidated. Keep this value
# consistent when reusing build artifacts.
#
# The Rust compiler will differentiate between versions of itself, including
# based on this string, which means that if you wish to be compatible with
# upstream Rust you need to set this to "". However, note that if you set this to "" but
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_ssa/src/back/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ impl MetadataLoader for DefaultMetadataLoader {
format!("failed to parse aix dylib '{}': {}", path.display(), e)
})?;

match archive.members().exactly_one() {
// FIXME: rewrite in terms of `#![feature(exact_length_collection)]`. See: #149266
match Itertools::exactly_one(archive.members()) {
Ok(lib) => {
let lib = lib.map_err(|e| {
format!("failed to parse aix dylib '{}': {}", path.display(), e)
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ impl<'a> Formatter<'a> {
//
// 2) Placeholders representation (e.g. format_args!("hello {name}\n"))
// ┌────────────────────────────────┐
// template: │ *const u8 │ ─▷ b"\x06hello \x80\x01\n\x00"
// template: │ *const u8 │ ─▷ b"\x06hello \xC0\x01\n\x00"
// ├────────────────────────────────┤
// args: │ &'a [Argument<'a>; _] 0│ (lower bit is 0 due to alignment of Argument type)
// └────────────────────────────────┘
Expand Down
56 changes: 56 additions & 0 deletions library/core/src/iter/traits/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4034,6 +4034,62 @@ pub trait Iterator {
{
unreachable!("Always specialized");
}

/// Checks if the iterator contains *exactly* one element.
/// If so, returns this one element.
///
/// See also [`collect_array`](Iterator::collect_array) for lengths other than `1`.
///
/// # Examples
///
/// ```
/// #![feature(exact_length_collection)]
///
/// assert_eq!([1].into_iter().exactly_one(), Some(1));
/// assert_eq!([].into_iter().exactly_one(), None::<()>);
///
/// // There is exactly one even integer in the array:
/// assert_eq!([1, 2, 3].into_iter().filter(|x| x % 2 == 0).exactly_one(), Some(2));
/// // But there are two odds, which is too many:
/// assert_eq!([1, 2, 3].into_iter().filter(|x| x % 2 == 1).exactly_one(), None);
/// ```
#[inline]
#[unstable(feature = "exact_length_collection", issue = "149266")]
fn exactly_one(self) -> Option<Self::Item>
where
Self: Sized,
{
self.collect_array::<1>().map(|[i]| i)
}

/// Checks if an iterator has *exactly* `N` elements.
/// If so, returns those `N` elements in an array.
///
/// See also [`exactly_one`](Iterator::exactly_one) when expecting a single element.
///
/// # Examples
///
/// ```
/// #![feature(exact_length_collection)]
///
/// assert_eq!([1, 2, 3, 4].into_iter().collect_array(), Some([1, 2, 3, 4]));
/// assert_eq!([1, 2].into_iter().chain([3, 4]).collect_array(), Some([1, 2, 3, 4]));
///
/// // Iterator contains too few elements:
/// assert_eq!([1, 2].into_iter().collect_array::<4>(), None);
/// // Iterator contains too many elements:
/// assert_eq!([1, 2, 3, 4, 5].into_iter().collect_array::<4>(), None);
/// // Taking 4 makes it work again:
/// assert_eq!([1, 2, 3, 4, 5].into_iter().take(4).collect_array(), Some([1, 2, 3, 4]));
/// ```
#[inline]
#[unstable(feature = "exact_length_collection", issue = "149266")]
fn collect_array<const N: usize>(mut self) -> Option<[Self::Item; N]>
where
Self: Sized,
{
self.next_chunk().ok().filter(|_| self.next().is_none())
}
}

trait SpecIterEq<B: Iterator>: Iterator {
Expand Down
9 changes: 8 additions & 1 deletion library/core/src/num/f128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1236,7 +1236,8 @@ impl f128 {
/// less than `min`. Otherwise this returns `self`.
///
/// Note that this function returns NaN if the initial value was NaN as
/// well.
/// well. If the result is zero and among the three inputs `self`, `min`, and `max` there are
/// zeros with different sign, either `0.0` or `-0.0` is returned non-deterministically.
///
/// # Panics
///
Expand All @@ -1253,6 +1254,12 @@ impl f128 {
/// assert!((0.0f128).clamp(-2.0, 1.0) == 0.0);
/// assert!((2.0f128).clamp(-2.0, 1.0) == 1.0);
/// assert!((f128::NAN).clamp(-2.0, 1.0).is_nan());
///
/// // These always returns zero, but the sign (which is ignored by `==`) is non-deterministic.
/// assert!((0.0f128).clamp(-0.0, -0.0) == 0.0);
/// assert!((1.0f128).clamp(-0.0, 0.0) == 0.0);
/// // This is definitely a negative zero.
/// assert!((-1.0f128).clamp(-0.0, 1.0).is_sign_negative());
/// # }
/// ```
#[inline]
Expand Down
9 changes: 8 additions & 1 deletion library/core/src/num/f16.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1215,7 +1215,8 @@ impl f16 {
/// less than `min`. Otherwise this returns `self`.
///
/// Note that this function returns NaN if the initial value was NaN as
/// well.
/// well. If the result is zero and among the three inputs `self`, `min`, and `max` there are
/// zeros with different sign, either `0.0` or `-0.0` is returned non-deterministically.
///
/// # Panics
///
Expand All @@ -1231,6 +1232,12 @@ impl f16 {
/// assert!((0.0f16).clamp(-2.0, 1.0) == 0.0);
/// assert!((2.0f16).clamp(-2.0, 1.0) == 1.0);
/// assert!((f16::NAN).clamp(-2.0, 1.0).is_nan());
///
/// // These always returns zero, but the sign (which is ignored by `==`) is non-deterministic.
/// assert!((0.0f16).clamp(-0.0, -0.0) == 0.0);
/// assert!((1.0f16).clamp(-0.0, 0.0) == 0.0);
/// // This is definitely a negative zero.
/// assert!((-1.0f16).clamp(-0.0, 1.0).is_sign_negative());
/// # }
/// ```
#[inline]
Expand Down
9 changes: 8 additions & 1 deletion library/core/src/num/f32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1395,7 +1395,8 @@ impl f32 {
/// less than `min`. Otherwise this returns `self`.
///
/// Note that this function returns NaN if the initial value was NaN as
/// well.
/// well. If the result is zero and among the three inputs `self`, `min`, and `max` there are
/// zeros with different sign, either `0.0` or `-0.0` is returned non-deterministically.
///
/// # Panics
///
Expand All @@ -1408,6 +1409,12 @@ impl f32 {
/// assert!((0.0f32).clamp(-2.0, 1.0) == 0.0);
/// assert!((2.0f32).clamp(-2.0, 1.0) == 1.0);
/// assert!((f32::NAN).clamp(-2.0, 1.0).is_nan());
///
/// // These always returns zero, but the sign (which is ignored by `==`) is non-deterministic.
/// assert!((0.0f32).clamp(-0.0, -0.0) == 0.0);
/// assert!((1.0f32).clamp(-0.0, 0.0) == 0.0);
/// // This is definitely a negative zero.
/// assert!((-1.0f32).clamp(-0.0, 1.0).is_sign_negative());
/// ```
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "clamp", since = "1.50.0")]
Expand Down
9 changes: 8 additions & 1 deletion library/core/src/num/f64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1393,7 +1393,8 @@ impl f64 {
/// less than `min`. Otherwise this returns `self`.
///
/// Note that this function returns NaN if the initial value was NaN as
/// well.
/// well. If the result is zero and among the three inputs `self`, `min`, and `max` there are
/// zeros with different sign, either `0.0` or `-0.0` is returned non-deterministically.
///
/// # Panics
///
Expand All @@ -1406,6 +1407,12 @@ impl f64 {
/// assert!((0.0f64).clamp(-2.0, 1.0) == 0.0);
/// assert!((2.0f64).clamp(-2.0, 1.0) == 1.0);
/// assert!((f64::NAN).clamp(-2.0, 1.0).is_nan());
///
/// // These always returns zero, but the sign (which is ignored by `==`) is non-deterministic.
/// assert!((0.0f64).clamp(-0.0, -0.0) == 0.0);
/// assert!((1.0f64).clamp(-0.0, 0.0) == 0.0);
/// // This is definitely a negative zero.
/// assert!((-1.0f64).clamp(-0.0, 1.0).is_sign_negative());
/// ```
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "clamp", since = "1.50.0")]
Expand Down
24 changes: 20 additions & 4 deletions library/core/src/num/int_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,8 @@ macro_rules! int_impl {
///
/// On big endian this is a no-op. On little endian the bytes are swapped.
///
/// See also [from_be_bytes()](Self::from_be_bytes).
///
/// # Examples
///
/// ```
Expand Down Expand Up @@ -402,6 +404,8 @@ macro_rules! int_impl {
///
/// On little endian this is a no-op. On big endian the bytes are swapped.
///
/// See also [from_le_bytes()](Self::from_le_bytes).
///
/// # Examples
///
/// ```
Expand All @@ -428,9 +432,15 @@ macro_rules! int_impl {
}
}

/// Converts `self` to big endian from the target's endianness.
/// Swaps bytes of `self` on little endian targets.
///
/// On big endian this is a no-op. On little endian the bytes are swapped.
/// On big endian this is a no-op.
///
/// The returned value has the same type as `self`, and will be interpreted
/// as (a potentially different) value of a native-endian
#[doc = concat!("`", stringify!($SelfT), "`.")]
///
/// See [`to_be_bytes()`](Self::to_be_bytes) for a type-safe alternative.
///
/// # Examples
///
Expand Down Expand Up @@ -459,9 +469,15 @@ macro_rules! int_impl {
}
}

/// Converts `self` to little endian from the target's endianness.
/// Swaps bytes of `self` on big endian targets.
///
/// On little endian this is a no-op. On big endian the bytes are swapped.
/// On little endian this is a no-op.
///
/// The returned value has the same type as `self`, and will be interpreted
/// as (a potentially different) value of a native-endian
#[doc = concat!("`", stringify!($SelfT), "`.")]
///
/// See [`to_le_bytes()`](Self::to_le_bytes) for a type-safe alternative.
///
/// # Examples
///
Expand Down
4 changes: 3 additions & 1 deletion src/bootstrap/src/core/build_steps/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,6 @@ pub(crate) fn is_ci_llvm_available_for_target(
("aarch64-unknown-linux-gnu", false),
("aarch64-apple-darwin", false),
("aarch64-pc-windows-msvc", false),
("i686-pc-windows-gnu", false),
("i686-pc-windows-msvc", false),
("i686-unknown-linux-gnu", false),
("x86_64-unknown-linux-gnu", true),
Expand All @@ -215,9 +214,11 @@ pub(crate) fn is_ci_llvm_available_for_target(
("x86_64-pc-windows-msvc", true),
// tier 2 with host tools
("aarch64-unknown-linux-musl", false),
("aarch64-pc-windows-gnullvm", false),
("arm-unknown-linux-gnueabi", false),
("arm-unknown-linux-gnueabihf", false),
("armv7-unknown-linux-gnueabihf", false),
("i686-pc-windows-gnu", false),
("loongarch64-unknown-linux-gnu", false),
("loongarch64-unknown-linux-musl", false),
("powerpc-unknown-linux-gnu", false),
Expand All @@ -226,6 +227,7 @@ pub(crate) fn is_ci_llvm_available_for_target(
("powerpc64le-unknown-linux-musl", false),
("riscv64gc-unknown-linux-gnu", false),
("s390x-unknown-linux-gnu", false),
("x86_64-pc-windows-gnullvm", true),
("x86_64-unknown-freebsd", false),
("x86_64-unknown-illumos", false),
("x86_64-unknown-linux-musl", false),
Expand Down
2 changes: 2 additions & 0 deletions src/bootstrap/src/core/download.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ pub(crate) fn is_download_ci_available(target_triple: &str, llvm_assertions: boo
// All tier 1 targets and tier 2 targets with host tools.
const SUPPORTED_PLATFORMS: &[&str] = &[
"aarch64-apple-darwin",
"aarch64-pc-windows-gnullvm",
"aarch64-pc-windows-msvc",
"aarch64-unknown-linux-gnu",
"aarch64-unknown-linux-musl",
Expand All @@ -465,6 +466,7 @@ pub(crate) fn is_download_ci_available(target_triple: &str, llvm_assertions: boo
"s390x-unknown-linux-gnu",
"x86_64-apple-darwin",
"x86_64-pc-windows-gnu",
"x86_64-pc-windows-gnullvm",
"x86_64-pc-windows-msvc",
"x86_64-unknown-freebsd",
"x86_64-unknown-illumos",
Expand Down
6 changes: 4 additions & 2 deletions src/librustdoc/html/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1126,7 +1126,8 @@ pub(crate) fn print_impl(
}
if impl_.kind.is_fake_variadic()
&& let Some(generics) = ty.generics()
&& let Ok(inner_type) = generics.exactly_one()
// FIXME: rewrite in terms of `#![feature(exact_length_collection)]`. See: #149266
&& let Ok(inner_type) = Itertools::exactly_one(generics)
{
let last = ty.last();
if f.alternate() {
Expand Down Expand Up @@ -1206,7 +1207,8 @@ impl clean::Impl {
}
} else if let clean::Type::Path { path } = type_
&& let Some(generics) = path.generics()
&& let Ok(ty) = generics.exactly_one()
// FIXME: rewrite in terms of `#![feature(exact_length_collection)]`. See: #149266
&& let Ok(ty) = Itertools::exactly_one(generics)
&& self.kind.is_fake_variadic()
{
print_anchor(path.def_id(), path.last(), cx).fmt(f)?;
Expand Down
8 changes: 5 additions & 3 deletions src/librustdoc/html/static/js/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -5050,9 +5050,11 @@ ${obj.displayPath}<span class="${type}">${name}</span>\
if (query.proposeCorrectionFrom !== null && isTypeSearch) {
const orig = query.proposeCorrectionFrom;
const targ = query.proposeCorrectionTo;
correctionOutput = "<h3 class=\"search-corrections\">" +
`Type "${orig}" not found and used as generic parameter. ` +
`Consider searching for "${targ}" instead.</h3>`;
let message = `Type "${orig}" not found and used as generic parameter.`;
if (targ !== null) {
message += ` Consider searching for "${targ}" instead.`;
}
correctionOutput = `<h3 class="search-corrections">${message}</h3>`;
}
if (firstResult.value) {
if (correctionOutput !== "") {
Expand Down
6 changes: 4 additions & 2 deletions src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive {
(matches!(v.data, VariantData::Unit(_, _)) && is_doc_hidden(cx.tcx.hir_attrs(v.hir_id)))
.then_some((v.def_id, v.span))
});
if let Ok((id, span)) = iter.exactly_one()
// FIXME: rewrite in terms of `#![feature(exact_length_collection)]`. See: #149266
if let Ok((id, span)) = Itertools::exactly_one(iter)
&& !find_attr!(cx.tcx.hir_attrs(item.hir_id()), AttributeKind::NonExhaustive(..))
{
self.potential_enums.push((item.owner_id.def_id, id, item.span, span));
Expand All @@ -104,7 +105,8 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive {
.iter()
.filter(|field| !cx.effective_visibilities.is_exported(field.def_id));
if fields.len() > 1
&& let Ok(field) = private_fields.exactly_one()
// FIXME: rewrite in terms of `#![feature(exact_length_collection)]`. See: #149266
&& let Ok(field) = Itertools::exactly_one(private_fields)
&& let TyKind::Tup([]) = field.ty.kind
{
span_lint_and_then(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,8 @@ fn parse_string(tt: &tt::TopSubtree) -> Result<(Symbol, Span), ExpandError> {
&& let DelimiterKind::Parenthesis | DelimiterKind::Invisible = sub.delimiter.kind
{
tt =
tt_iter.exactly_one().map_err(|_| sub.delimiter.open.cover(sub.delimiter.close))?;
// FIXME: rewrite in terms of `#![feature(exact_length_collection)]`. See: #149266
Itertools::exactly_one(tt_iter).map_err(|_| sub.delimiter.open.cover(sub.delimiter.close))?;
}

match tt {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ pub(crate) fn convert_bool_then_to_if(acc: &mut Assists, ctx: &AssistContext<'_>
let name_ref = ctx.find_node_at_offset::<ast::NameRef>()?;
let mcall = name_ref.syntax().parent().and_then(ast::MethodCallExpr::cast)?;
let receiver = mcall.receiver()?;
let closure_body = mcall.arg_list()?.args().exactly_one().ok()?;
// FIXME: rewrite in terms of `#![feature(exact_length_collection)]`. See: #149266
let closure_body = Itertools::exactly_one(mcall.arg_list()?.args()).ok()?;
let closure_body = match closure_body {
ast::Expr::ClosureExpr(expr) => expr.body()?,
_ => return None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ fn extract_range(iterable: &ast::Expr) -> Option<(ast::Expr, Option<ast::Expr>,
(range.start()?, range.end(), make::expr_literal("1").into(), inclusive)
}
ast::Expr::MethodCallExpr(call) if call.name_ref()?.text() == "step_by" => {
let [step] = call.arg_list()?.args().collect_array()?;
let [step] = Itertools::collect_array(call.arg_list()?.args())?;
let (start, end, _, inclusive) = extract_range(&call.receiver()?)?;
(start, end, step, inclusive)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
let completions = completion_list_with_config_raw(TEST_CONFIG, ra_fixture, true, None);
let (db, position) = position(ra_fixture);
let mut actual = db.file_text(position.file_id).text(&db).to_string();
completions
.into_iter()
.exactly_one()
// FIXME: rewrite in terms of `#![feature(exact_length_collection)]`. See: #149266
Itertools::exactly_one(completions.into_iter())
.expect("more than one completion")
.text_edit
.apply(&mut actual);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ impl Project<'_> {
let mut buf = Vec::new();
flags::Lsif::run(
flags::Lsif {
path: tmp_dir_path.join(self.roots.iter().exactly_one().unwrap()).into(),
// FIXME: rewrite in terms of `#![feature(exact_length_collection)]`. See: #149266
path: tmp_dir_path.join(Itertools::exactly_one(self.roots.iter()).unwrap()).into(),
exclude_vendored_libraries: false,
},
&mut buf,
Expand Down
Loading
Loading