Skip to content

Delegate to inner vec::IntoIter from env::ArgsOs #139847

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
73 changes: 72 additions & 1 deletion library/std/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@

use crate::error::Error;
use crate::ffi::{OsStr, OsString};
use crate::num::NonZero;
use crate::ops::Try;
use crate::path::{Path, PathBuf};
use crate::sys::{env as env_imp, os as os_imp};
use crate::{fmt, io, sys};
use crate::{array, fmt, io, sys};

/// Returns the current working directory as a [`PathBuf`].
///
Expand Down Expand Up @@ -872,19 +874,36 @@ impl !Sync for Args {}
#[stable(feature = "env", since = "1.0.0")]
impl Iterator for Args {
type Item = String;

fn next(&mut self) -> Option<String> {
self.inner.next().map(|s| s.into_string().unwrap())
}

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}

// Methods which skip args cannot simply delegate to the inner iterator,
// because `env::args` states that we will "panic during iteration if any
// argument to the process is not valid Unicode".
//
// This offers two possible interpretations:
// - a skipped argument is never encountered "during iteration"
// - even a skipped argument is encountered "during iteration"
//
// As a panic can be observed, we err towards validating even skipped
// arguments for now, though this is not explicitly promised by the API.
}

#[stable(feature = "env", since = "1.0.0")]
impl ExactSizeIterator for Args {
#[inline]
fn len(&self) -> usize {
self.inner.len()
}

#[inline]
fn is_empty(&self) -> bool {
self.inner.is_empty()
}
Expand Down Expand Up @@ -914,29 +933,81 @@ impl !Sync for ArgsOs {}
#[stable(feature = "env", since = "1.0.0")]
impl Iterator for ArgsOs {
type Item = OsString;

#[inline]
fn next(&mut self) -> Option<OsString> {
self.inner.next()
}

#[inline]
fn next_chunk<const N: usize>(
&mut self,
) -> Result<[OsString; N], array::IntoIter<OsString, N>> {
self.inner.next_chunk()
}

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}

#[inline]
fn count(self) -> usize {
self.inner.len()
}

#[inline]
fn last(self) -> Option<OsString> {
self.inner.last()
}

#[inline]
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
self.inner.advance_by(n)
}

#[inline]
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
where
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
{
self.inner.try_fold(init, f)
}

#[inline]
fn fold<B, F>(self, init: B, f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
self.inner.fold(init, f)
}
}

#[stable(feature = "env", since = "1.0.0")]
impl ExactSizeIterator for ArgsOs {
#[inline]
fn len(&self) -> usize {
self.inner.len()
}

#[inline]
fn is_empty(&self) -> bool {
self.inner.is_empty()
}
}

#[stable(feature = "env_iterators", since = "1.12.0")]
impl DoubleEndedIterator for ArgsOs {
#[inline]
fn next_back(&mut self) -> Option<OsString> {
self.inner.next_back()
}

#[inline]
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
self.inner.advance_back_by(n)
}
}

#[stable(feature = "std_debug", since = "1.16.0")]
Expand Down
3 changes: 3 additions & 0 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,8 @@
#![feature(formatting_options)]
#![feature(if_let_guard)]
#![feature(intra_doc_pointers)]
#![feature(iter_advance_by)]
#![feature(iter_next_chunk)]
#![feature(lang_items)]
#![feature(let_chains)]
#![feature(link_cfg)]
Expand All @@ -321,6 +323,7 @@
#![feature(strict_provenance_lints)]
#![feature(thread_local)]
#![feature(try_blocks)]
#![feature(try_trait_v2)]
#![feature(type_alias_impl_trait)]
// tidy-alphabetical-end
//
Expand Down
66 changes: 62 additions & 4 deletions library/std/src/sys/args/common.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use crate::ffi::OsString;
use crate::{fmt, vec};
use crate::num::NonZero;
use crate::ops::Try;
use crate::{array, fmt, vec};

pub struct Args {
iter: vec::IntoIter<OsString>,
Expand All @@ -9,6 +11,7 @@ impl !Send for Args {}
impl !Sync for Args {}

impl Args {
#[inline]
pub(super) fn new(args: Vec<OsString>) -> Self {
Args { iter: args.into_iter() }
}
Expand All @@ -22,22 +25,77 @@ impl fmt::Debug for Args {

impl Iterator for Args {
type Item = OsString;

#[inline]
fn next(&mut self) -> Option<OsString> {
self.iter.next()
}

#[inline]
fn next_chunk<const N: usize>(
&mut self,
) -> Result<[OsString; N], array::IntoIter<OsString, N>> {
self.iter.next_chunk()
}

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}

impl ExactSizeIterator for Args {
fn len(&self) -> usize {
#[inline]
fn count(self) -> usize {
self.iter.len()
}

#[inline]
fn last(mut self) -> Option<OsString> {
self.iter.next_back()
}

#[inline]
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
self.iter.advance_by(n)
}

#[inline]
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
where
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
{
self.iter.try_fold(init, f)
}

#[inline]
fn fold<B, F>(self, init: B, f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
self.iter.fold(init, f)
}
}

impl DoubleEndedIterator for Args {
#[inline]
fn next_back(&mut self) -> Option<OsString> {
self.iter.next_back()
}

#[inline]
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
self.iter.advance_back_by(n)
}
}

impl ExactSizeIterator for Args {
#[inline]
fn len(&self) -> usize {
self.iter.len()
}

#[inline]
fn is_empty(&self) -> bool {
self.iter.is_empty()
}
}
68 changes: 58 additions & 10 deletions library/std/src/sys/args/sgx.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#![allow(fuzzy_provenance_casts)] // FIXME: this module systematically confuses pointers and integers

use crate::ffi::OsString;
use crate::num::NonZero;
use crate::ops::Try;
use crate::sync::atomic::{Atomic, AtomicUsize, Ordering};
use crate::sys::os_str::Buf;
use crate::sys::pal::abi::usercalls::alloc;
Expand Down Expand Up @@ -28,35 +30,81 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {

pub fn args() -> Args {
let args = unsafe { (ARGS.load(Ordering::Relaxed) as *const ArgsStore).as_ref() };
if let Some(args) = args { Args(args.iter()) } else { Args([].iter()) }
let slice = args.map(|args| args.as_slice()).unwrap_or(&[]);
Args { iter: slice.iter() }
}

pub struct Args(slice::Iter<'static, OsString>);
pub struct Args {
iter: slice::Iter<'static, OsString>,
}

impl fmt::Debug for Args {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.as_slice().fmt(f)
self.iter.as_slice().fmt(f)
}
}

impl Iterator for Args {
type Item = OsString;

fn next(&mut self) -> Option<OsString> {
self.0.next().cloned()
self.iter.next().cloned()
}

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
self.iter.size_hint()
}
}

impl ExactSizeIterator for Args {
fn len(&self) -> usize {
self.0.len()
#[inline]
fn count(self) -> usize {
self.iter.len()
}

fn last(self) -> Option<OsString> {
self.iter.last().cloned()
}

#[inline]
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
self.iter.advance_by(n)
}

fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
where
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
{
self.iter.by_ref().cloned().try_fold(init, f)
}

fn fold<B, F>(self, init: B, f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
self.iter.cloned().fold(init, f)
}
}

impl DoubleEndedIterator for Args {
fn next_back(&mut self) -> Option<OsString> {
self.0.next_back().cloned()
self.iter.next_back().cloned()
}

#[inline]
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
self.iter.advance_back_by(n)
}
}

impl ExactSizeIterator for Args {
#[inline]
fn len(&self) -> usize {
self.iter.len()
}

#[inline]
fn is_empty(&self) -> bool {
self.iter.is_empty()
}
}
18 changes: 12 additions & 6 deletions library/std/src/sys/args/unsupported.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,28 @@ impl fmt::Debug for Args {

impl Iterator for Args {
type Item = OsString;

#[inline]
fn next(&mut self) -> Option<OsString> {
None
}

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, Some(0))
}
}

impl ExactSizeIterator for Args {
fn len(&self) -> usize {
0
}
}

impl DoubleEndedIterator for Args {
#[inline]
fn next_back(&mut self) -> Option<OsString> {
None
}
}

impl ExactSizeIterator for Args {
#[inline]
fn len(&self) -> usize {
0
}
}
Loading