Skip to content
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

Rollup of 6 pull requests #122846

Closed
wants to merge 14 commits into from
Closed
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
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ language_item_table! {
FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None;

Iterator, sym::iterator, iterator_trait, Target::Trait, GenericRequirement::Exact(0);
FusedIterator, sym::fused_iterator, fused_iterator_trait, Target::Trait, GenericRequirement::Exact(0);
Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0);
AsyncIterator, sym::async_iterator, async_iterator_trait, Target::Trait, GenericRequirement::Exact(0);

Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ symbols! {
FromResidual,
FsOpenOptions,
FsPermissions,
FusedIterator,
Future,
FutureOutput,
GlobalAlloc,
Expand Down Expand Up @@ -886,6 +887,7 @@ symbols! {
fsub_algebraic,
fsub_fast,
fundamental,
fused_iterator,
future,
future_trait,
gdb_script_file,
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_trait_selection/src/solve/assembly/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,13 @@ pub(super) trait GoalKind<'tcx>:
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;

/// A coroutine (that comes from a `gen` desugaring) is known to implement
/// `FusedIterator`
fn consider_builtin_fused_iterator_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;

fn consider_builtin_async_iterator_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
Expand Down Expand Up @@ -497,6 +504,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
G::consider_builtin_future_candidate(self, goal)
} else if lang_items.iterator_trait() == Some(trait_def_id) {
G::consider_builtin_iterator_candidate(self, goal)
} else if lang_items.fused_iterator_trait() == Some(trait_def_id) {
G::consider_builtin_fused_iterator_candidate(self, goal)
} else if lang_items.async_iterator_trait() == Some(trait_def_id) {
G::consider_builtin_async_iterator_candidate(self, goal)
} else if lang_items.coroutine_trait() == Some(trait_def_id) {
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
)
}

fn consider_builtin_fused_iterator_candidate(
_ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx> {
bug!("`FusedIterator` does not have an associated type: {:?}", goal);
}

fn consider_builtin_async_iterator_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
Expand Down
22 changes: 22 additions & 0 deletions compiler/rustc_trait_selection/src/solve/trait_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,28 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}

fn consider_builtin_fused_iterator_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx> {
if goal.predicate.polarity != ty::ImplPolarity::Positive {
return Err(NoSolution);
}

let ty::Coroutine(def_id, _) = *goal.predicate.self_ty().kind() else {
return Err(NoSolution);
};

// Coroutines are not iterators unless they come from `gen` desugaring
let tcx = ecx.tcx();
if !tcx.coroutine_is_gen(def_id) {
return Err(NoSolution);
}

// Gen coroutines unconditionally implement `FusedIterator`
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}

fn consider_builtin_async_iterator_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.assemble_future_candidates(obligation, &mut candidates);
} else if lang_items.iterator_trait() == Some(def_id) {
self.assemble_iterator_candidates(obligation, &mut candidates);
} else if lang_items.fused_iterator_trait() == Some(def_id) {
self.assemble_fused_iterator_candidates(obligation, &mut candidates);
} else if lang_items.async_iterator_trait() == Some(def_id) {
self.assemble_async_iterator_candidates(obligation, &mut candidates);
} else if lang_items.async_fn_kind_helper() == Some(def_id) {
Expand Down Expand Up @@ -302,14 +304,31 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
candidates: &mut SelectionCandidateSet<'tcx>,
) {
let self_ty = obligation.self_ty().skip_binder();
if let ty::Coroutine(did, ..) = self_ty.kind() {
// gen constructs get lowered to a special kind of coroutine that
// should directly `impl Iterator`.
if self.tcx().coroutine_is_gen(*did) {
debug!(?self_ty, ?obligation, "assemble_iterator_candidates",);
// gen constructs get lowered to a special kind of coroutine that
// should directly `impl Iterator`.
if let ty::Coroutine(did, ..) = self_ty.kind()
&& self.tcx().coroutine_is_gen(*did)
{
debug!(?self_ty, ?obligation, "assemble_iterator_candidates",);

candidates.vec.push(IteratorCandidate);
}
candidates.vec.push(IteratorCandidate);
}
}

fn assemble_fused_iterator_candidates(
&mut self,
obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
let self_ty = obligation.self_ty().skip_binder();
// gen constructs get lowered to a special kind of coroutine that
// should directly `impl FusedIterator`.
if let ty::Coroutine(did, ..) = self_ty.kind()
&& self.tcx().coroutine_is_gen(*did)
{
debug!(?self_ty, ?obligation, "assemble_fused_iterator_candidates",);

candidates.vec.push(BuiltinCandidate { has_nested: false });
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.copy_clone_conditions(obligation)
} else if Some(trait_def) == lang_items.clone_trait() {
self.copy_clone_conditions(obligation)
} else if Some(trait_def) == lang_items.fused_iterator_trait() {
self.fused_iterator_conditions(obligation)
} else {
bug!("unexpected builtin trait {:?}", trait_def)
};
Expand Down
14 changes: 14 additions & 0 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2259,6 +2259,20 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
}
}

fn fused_iterator_conditions(
&mut self,
obligation: &PolyTraitObligation<'tcx>,
) -> BuiltinImplConditions<'tcx> {
let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
if let ty::Coroutine(did, ..) = *self_ty.kind()
&& self.tcx().coroutine_is_gen(did)
{
BuiltinImplConditions::Where(ty::Binder::dummy(Vec::new()))
} else {
BuiltinImplConditions::None
}
}

/// For default impls, we need to break apart a type into its
/// "constituent types" -- meaning, the types that it contains.
///
Expand Down
5 changes: 3 additions & 2 deletions library/alloc/src/collections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT;
/// `BTreeMap` that observed the logic error and not result in undefined behavior. This could
/// include panics, incorrect results, aborts, memory leaks, and non-termination.
///
/// Iterators obtained from functions such as [`BTreeMap::iter`], [`BTreeMap::values`], or
/// Iterators obtained from functions such as [`BTreeMap::iter`], [`BTreeMap::into_iter`], [`BTreeMap::values`], or
/// [`BTreeMap::keys`] produce their items in order by key, and take worst-case logarithmic and
/// amortized constant time per item returned.
///
Expand Down Expand Up @@ -415,7 +415,7 @@ impl<'a, K: 'a, V: 'a> Default for IterMut<'a, K, V> {
}
}

/// An owning iterator over the entries of a `BTreeMap`.
/// An owning iterator over the entries of a `BTreeMap`, sorted by key.
///
/// This `struct` is created by the [`into_iter`] method on [`BTreeMap`]
/// (provided by the [`IntoIterator`] trait). See its documentation for more.
Expand Down Expand Up @@ -1637,6 +1637,7 @@ impl<K, V, A: Allocator + Clone> IntoIterator for BTreeMap<K, V, A> {
type Item = (K, V);
type IntoIter = IntoIter<K, V, A>;

/// Gets an owning iterator over the entries of the map, sorted by key.
fn into_iter(self) -> IntoIter<K, V, A> {
let mut me = ManuallyDrop::new(self);
if let Some(root) = me.root.take() {
Expand Down
6 changes: 3 additions & 3 deletions library/alloc/src/collections/btree/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crate::alloc::{Allocator, Global};
/// `BTreeSet` that observed the logic error and not result in undefined behavior. This could
/// include panics, incorrect results, aborts, memory leaks, and non-termination.
///
/// Iterators returned by [`BTreeSet::iter`] produce their items in order, and take worst-case
/// Iterators returned by [`BTreeSet::iter`] and [`BTreeSet::into_iter`] produce their items in order, and take worst-case
/// logarithmic and amortized constant time per item returned.
///
/// [`Cell`]: core::cell::Cell
Expand Down Expand Up @@ -140,7 +140,7 @@ impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
}
}

/// An owning iterator over the items of a `BTreeSet`.
/// An owning iterator over the items of a `BTreeSet` in ascending order.
///
/// This `struct` is created by the [`into_iter`] method on [`BTreeSet`]
/// (provided by the [`IntoIterator`] trait). See its documentation for more.
Expand Down Expand Up @@ -1237,7 +1237,7 @@ impl<T, A: Allocator + Clone> IntoIterator for BTreeSet<T, A> {
type Item = T;
type IntoIter = IntoIter<T, A>;

/// Gets an iterator for moving out the `BTreeSet`'s contents.
/// Gets an iterator for moving out the `BTreeSet`'s contents in ascending order.
///
/// # Examples
///
Expand Down
1 change: 1 addition & 0 deletions library/core/src/iter/traits/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub unsafe trait TrustedFused {}
#[rustc_unsafe_specialization_marker]
// FIXME: this should be a #[marker] and have another blanket impl for T: TrustedFused
// but that ICEs iter::Fuse specializations.
#[cfg_attr(not(bootstrap), lang = "fused_iterator")]
pub trait FusedIterator: Iterator {}

#[stable(feature = "fused", since = "1.26.0")]
Expand Down
26 changes: 26 additions & 0 deletions library/std/src/os/freebsd/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#![unstable(feature = "unix_socket_ancillary_data", issue = "76915")]

use crate::ffi::CStr;
use crate::io;
use crate::os::unix::net;
use crate::sealed::Sealed;
Expand Down Expand Up @@ -40,6 +41,15 @@ pub trait UnixSocketExt: Sealed {
/// ```
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
fn set_local_creds_persistent(&self, local_creds_persistent: bool) -> io::Result<()>;

/// Get a filter name if one had been set previously on the socket.
#[unstable(feature = "acceptfilter", issue = "121891")]
fn acceptfilter(&self) -> io::Result<&CStr>;

/// Set or disable a filter on the socket to filter incoming connections
/// to defer it before accept(2)
#[unstable(feature = "acceptfilter", issue = "121891")]
fn set_acceptfilter(&self, name: &CStr) -> io::Result<()>;
}

#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
Expand All @@ -51,6 +61,14 @@ impl UnixSocketExt for net::UnixDatagram {
fn set_local_creds_persistent(&self, local_creds_persistent: bool) -> io::Result<()> {
self.as_inner().set_local_creds_persistent(local_creds_persistent)
}

fn acceptfilter(&self) -> io::Result<&CStr> {
self.as_inner().acceptfilter()
}

fn set_acceptfilter(&self, name: &CStr) -> io::Result<()> {
self.as_inner().set_acceptfilter(name)
}
}

#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
Expand All @@ -62,4 +80,12 @@ impl UnixSocketExt for net::UnixStream {
fn set_local_creds_persistent(&self, local_creds_persistent: bool) -> io::Result<()> {
self.as_inner().set_local_creds_persistent(local_creds_persistent)
}

fn acceptfilter(&self) -> io::Result<&CStr> {
self.as_inner().acceptfilter()
}

fn set_acceptfilter(&self, name: &CStr) -> io::Result<()> {
self.as_inner().set_acceptfilter(name)
}
}
26 changes: 26 additions & 0 deletions library/std/src/os/netbsd/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#![unstable(feature = "unix_socket_ancillary_data", issue = "76915")]

use crate::ffi::CStr;
use crate::io;
use crate::os::unix::net;
use crate::sealed::Sealed;
Expand Down Expand Up @@ -40,6 +41,15 @@ pub trait UnixSocketExt: Sealed {
/// ```
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
fn set_local_creds(&self, local_creds: bool) -> io::Result<()>;

/// Get a filter name if one had been set previously on the socket.
#[unstable(feature = "acceptfilter", issue = "121891")]
fn acceptfilter(&self) -> io::Result<&CStr>;

/// Set or disable a filter on the socket to filter incoming connections
/// to defer it before accept(2)
#[unstable(feature = "acceptfilter", issue = "121891")]
fn set_acceptfilter(&self, name: &CStr) -> io::Result<()>;
}

#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
Expand All @@ -51,6 +61,14 @@ impl UnixSocketExt for net::UnixDatagram {
fn set_local_creds(&self, local_creds: bool) -> io::Result<()> {
self.as_inner().set_local_creds(local_creds)
}

fn acceptfilter(&self) -> io::Result<&CStr> {
self.as_inner().acceptfilter()
}

fn set_acceptfilter(&self, name: &CStr) -> io::Result<()> {
self.as_inner().set_acceptfilter(name)
}
}

#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
Expand All @@ -62,4 +80,12 @@ impl UnixSocketExt for net::UnixStream {
fn set_local_creds(&self, local_creds: bool) -> io::Result<()> {
self.as_inner().set_local_creds(local_creds)
}

fn acceptfilter(&self) -> io::Result<&CStr> {
self.as_inner().acceptfilter()
}

fn set_acceptfilter(&self, name: &CStr) -> io::Result<()> {
self.as_inner().set_acceptfilter(name)
}
}
31 changes: 31 additions & 0 deletions library/std/src/sys/pal/unix/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,37 @@ impl Socket {
Ok(raw as u32)
}

#[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
pub fn set_acceptfilter(&self, name: &CStr) -> io::Result<()> {
if !name.to_bytes().is_empty() {
const AF_NAME_MAX: usize = 16;
let mut buf = [0; AF_NAME_MAX];
for (src, dst) in name.to_bytes().iter().zip(&mut buf[..AF_NAME_MAX - 1]) {
*dst = *src as i8;
}
let mut arg: libc::accept_filter_arg = unsafe { mem::zeroed() };
arg.af_name = buf;
setsockopt(self, libc::SOL_SOCKET, libc::SO_ACCEPTFILTER, &mut arg)
} else {
setsockopt(
self,
libc::SOL_SOCKET,
libc::SO_ACCEPTFILTER,
core::ptr::null_mut() as *mut c_void,
)
}
}

#[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
pub fn acceptfilter(&self) -> io::Result<&CStr> {
let arg: libc::accept_filter_arg =
getsockopt(self, libc::SOL_SOCKET, libc::SO_ACCEPTFILTER)?;
let s: &[u8] =
unsafe { core::slice::from_raw_parts(arg.af_name.as_ptr() as *const u8, 16) };
let name = CStr::from_bytes_with_nul(s).unwrap();
Ok(name)
}

#[cfg(any(target_os = "android", target_os = "linux",))]
pub fn set_passcred(&self, passcred: bool) -> io::Result<()> {
setsockopt(self, libc::SOL_SOCKET, libc::SO_PASSCRED, passcred as libc::c_int)
Expand Down
Loading
Loading