Rollup merge of #149270 - jdonszelmann:exact-length-collection, r=Mark-Simulacrum
implement `Iterator::{exactly_one, collect_array}`
As per https://github.com/rust-lang/rust/issues/149266
This commit is contained in:
commit
3a62a46006
11 changed files with 81 additions and 17 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
@ -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)?;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use std::mem::MaybeUninit;
|
|||
trait CollectSlice<'a>: Iterator {
|
||||
fn inner_array<const N: usize>(&mut self) -> [Self::Item; N];
|
||||
|
||||
fn collect_array<const N: usize>(&mut self) -> [Self::Item; N] {
|
||||
fn custom_collect_array<const N: usize>(&mut self) -> [Self::Item; N] {
|
||||
let result = self.inner_array();
|
||||
assert!(self.next().is_none());
|
||||
result
|
||||
|
|
@ -34,5 +34,5 @@ where
|
|||
|
||||
fn main() {
|
||||
let mut foos = [0u64; 9].iter().cloned();
|
||||
let _bar: [u64; 9] = foos.collect_array::<9_usize>();
|
||||
let _bar: [u64; 9] = foos.custom_collect_array::<9_usize>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,10 +29,11 @@ where
|
|||
|
||||
fn main() {
|
||||
assert_eq!(
|
||||
[[1, 2], [3, 4]]
|
||||
CollectArray::collect_array(
|
||||
&mut [[1, 2], [3, 4]]
|
||||
.iter()
|
||||
.map(|row| row.iter().collect_array())
|
||||
.collect_array(),
|
||||
.map(|row| CollectArray::collect_array(&mut row.iter()))
|
||||
),
|
||||
[[&1, &2], [&3, &4]]
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue