Auto merge of #151875 - JonathanBrouwer:rollup-OPCJQtC, r=JonathanBrouwer
Rollup of 2 pull requests Successful merges: - rust-lang/rust#151281 (constify `Iterator`, take IV) - rust-lang/rust#151873 (resolve: Remove `force` parameter from `resolve_ident_in_scope`)
This commit is contained in:
commit
44e34e1ac6
29 changed files with 286 additions and 85 deletions
|
|
@ -388,3 +388,15 @@ impl<S: Stage> CombineAttributeParser<S> for RustcLayoutParser {
|
|||
result
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RustcNonConstTraitMethodParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcNonConstTraitMethodParser {
|
||||
const PATH: &'static [Symbol] = &[sym::rustc_non_const_trait_method];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Method(MethodKind::Trait { body: true })),
|
||||
Allow(Target::Method(MethodKind::Trait { body: false })),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonConstTraitMethod;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,9 +79,9 @@ use crate::attributes::rustc_internal::{
|
|||
RustcLayoutScalarValidRangeStartParser, RustcLegacyConstGenericsParser,
|
||||
RustcLintOptDenyFieldAccessParser, RustcLintOptTyParser, RustcLintQueryInstabilityParser,
|
||||
RustcLintUntrackedQueryInformationParser, RustcMainParser, RustcMustImplementOneOfParser,
|
||||
RustcNeverReturnsNullPointerParser, RustcNoImplicitAutorefsParser, RustcNounwindParser,
|
||||
RustcObjectLifetimeDefaultParser, RustcOffloadKernelParser, RustcScalableVectorParser,
|
||||
RustcSimdMonomorphizeLaneLimitParser,
|
||||
RustcNeverReturnsNullPointerParser, RustcNoImplicitAutorefsParser,
|
||||
RustcNonConstTraitMethodParser, RustcNounwindParser, RustcObjectLifetimeDefaultParser,
|
||||
RustcOffloadKernelParser, RustcScalableVectorParser, RustcSimdMonomorphizeLaneLimitParser,
|
||||
};
|
||||
use crate::attributes::semantics::MayDangleParser;
|
||||
use crate::attributes::stability::{
|
||||
|
|
@ -305,6 +305,7 @@ attribute_parsers!(
|
|||
Single<WithoutArgs<RustcMainParser>>,
|
||||
Single<WithoutArgs<RustcNeverReturnsNullPointerParser>>,
|
||||
Single<WithoutArgs<RustcNoImplicitAutorefsParser>>,
|
||||
Single<WithoutArgs<RustcNonConstTraitMethodParser>>,
|
||||
Single<WithoutArgs<RustcNounwindParser>>,
|
||||
Single<WithoutArgs<RustcOffloadKernelParser>>,
|
||||
Single<WithoutArgs<RustcPassIndirectlyInNonRusticAbisParser>>,
|
||||
|
|
|
|||
|
|
@ -774,16 +774,16 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||
|
||||
// Attempting to call a trait method?
|
||||
if let Some(trait_did) = tcx.trait_of_assoc(callee) {
|
||||
// We can't determine the actual callee here, so we have to do different checks
|
||||
// than usual.
|
||||
// We can't determine the actual callee (the underlying impl of the trait) here, so we have
|
||||
// to do different checks than usual.
|
||||
|
||||
trace!("attempting to call a trait method");
|
||||
let trait_is_const = tcx.is_const_trait(trait_did);
|
||||
let is_const = tcx.constness(callee) == hir::Constness::Const;
|
||||
|
||||
// Only consider a trait to be const if the const conditions hold.
|
||||
// Otherwise, it's really misleading to call something "conditionally"
|
||||
// const when it's very obviously not conditionally const.
|
||||
if trait_is_const && has_const_conditions == Some(ConstConditionsHold::Yes) {
|
||||
if is_const && has_const_conditions == Some(ConstConditionsHold::Yes) {
|
||||
// Trait calls are always conditionally-const.
|
||||
self.check_op(ops::ConditionallyConstCall {
|
||||
callee,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::{
|
||||
Constness, ExprKind, ForeignItemKind, ImplItem, ImplItemImplKind, ImplItemKind, Item, ItemKind,
|
||||
Node, TraitItem, TraitItemKind, VariantData,
|
||||
Node, TraitItem, TraitItemKind, VariantData, find_attr,
|
||||
};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
|
@ -36,7 +37,13 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Constness {
|
|||
Constness::NotConst => tcx.constness(tcx.local_parent(def_id)),
|
||||
}
|
||||
}
|
||||
Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(..), .. }) => tcx.trait_def(tcx.local_parent(def_id)).constness,
|
||||
Node::TraitItem(ti @ TraitItem { kind: TraitItemKind::Fn(..), .. }) => {
|
||||
if find_attr!(tcx.hir_attrs(ti.hir_id()), AttributeKind::RustcNonConstTraitMethod) {
|
||||
Constness::NotConst
|
||||
} else {
|
||||
tcx.trait_def(tcx.local_parent(def_id)).constness
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
tcx.dcx().span_bug(
|
||||
tcx.def_span(def_id),
|
||||
|
|
|
|||
|
|
@ -1329,6 +1329,12 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
"`#[rustc_has_incoherent_inherent_impls]` allows the addition of incoherent inherent impls for \
|
||||
the given type by annotating all impl items with `#[rustc_allow_incoherent_impl]`"
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_non_const_trait_method, AttributeType::Normal, template!(Word),
|
||||
ErrorFollowing, EncodeCrossCrate::No,
|
||||
"`#[rustc_non_const_trait_method]` should only used by the standard library to mark trait methods \
|
||||
as non-const to allow large traits an easier transition to const"
|
||||
),
|
||||
|
||||
BuiltinAttribute {
|
||||
name: sym::rustc_diagnostic_item,
|
||||
|
|
|
|||
|
|
@ -1096,6 +1096,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[rustc_no_implicit_autorefs]`
|
||||
RustcNoImplicitAutorefs,
|
||||
|
||||
/// Represents `#[rustc_non_const_trait_method]`.
|
||||
RustcNonConstTraitMethod,
|
||||
|
||||
/// Represents `#[rustc_nounwind]`
|
||||
RustcNounwind,
|
||||
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ impl AttributeKind {
|
|||
RustcMustImplementOneOf { .. } => No,
|
||||
RustcNeverReturnsNullPointer => Yes,
|
||||
RustcNoImplicitAutorefs => Yes,
|
||||
RustcNonConstTraitMethod => No, // should be reported via other queries like `constness`
|
||||
RustcNounwind => No,
|
||||
RustcObjcClass { .. } => No,
|
||||
RustcObjcSelector { .. } => No,
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ fn compare_method_predicate_entailment<'tcx>(
|
|||
trait_m_predicates.instantiate_own(tcx, trait_to_impl_args).map(|(predicate, _)| predicate),
|
||||
);
|
||||
|
||||
let is_conditionally_const = tcx.is_conditionally_const(impl_def_id);
|
||||
let is_conditionally_const = tcx.is_conditionally_const(impl_m.def_id);
|
||||
if is_conditionally_const {
|
||||
// Augment the hybrid param-env with the const conditions
|
||||
// of the impl header and the trait method.
|
||||
|
|
|
|||
|
|
@ -2086,8 +2086,16 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
DefKind::Impl { of_trait: false } => {
|
||||
self.constness(def_id) == hir::Constness::Const
|
||||
}
|
||||
DefKind::Impl { of_trait: true } | DefKind::Trait => {
|
||||
self.is_conditionally_const(parent_def_id)
|
||||
DefKind::Impl { of_trait: true } => {
|
||||
let Some(trait_method_did) = self.trait_item_of(def_id) else {
|
||||
return false;
|
||||
};
|
||||
self.constness(trait_method_did) == hir::Constness::Const
|
||||
&& self.is_conditionally_const(parent_def_id)
|
||||
}
|
||||
DefKind::Trait => {
|
||||
self.constness(def_id) == hir::Constness::Const
|
||||
&& self.is_conditionally_const(parent_def_id)
|
||||
}
|
||||
_ => bug!("unexpected parent item of associated fn: {parent_def_id:?}"),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -310,6 +310,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| AttributeKind::RustcMain
|
||||
| AttributeKind::RustcNeverReturnsNullPointer
|
||||
| AttributeKind::RustcNoImplicitAutorefs
|
||||
| AttributeKind::RustcNonConstTraitMethod
|
||||
| AttributeKind::RustcNounwind
|
||||
| AttributeKind::RustcObjcClass { .. }
|
||||
| AttributeKind::RustcObjcSelector { .. }
|
||||
|
|
@ -335,7 +336,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| AttributeKind::Used { .. }
|
||||
| AttributeKind::WindowsSubsystem(..)
|
||||
// tidy-alphabetical-end
|
||||
|
||||
) => { /* do nothing */ }
|
||||
Attribute::Unparsed(attr_item) => {
|
||||
style = Some(attr_item.style);
|
||||
|
|
|
|||
|
|
@ -1709,7 +1709,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::All(ns),
|
||||
parent_scope,
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
None,
|
||||
) else {
|
||||
|
|
@ -2546,7 +2545,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::All(ns_to_try),
|
||||
parent_scope,
|
||||
None,
|
||||
false,
|
||||
ignore_decl,
|
||||
ignore_import,
|
||||
)
|
||||
|
|
@ -2650,7 +2648,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::All(ValueNS),
|
||||
parent_scope,
|
||||
None,
|
||||
false,
|
||||
ignore_decl,
|
||||
ignore_import,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -350,7 +350,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::Module(ns, module),
|
||||
parent_scope,
|
||||
finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),
|
||||
finalize.is_some(),
|
||||
ignore_decl,
|
||||
None,
|
||||
)
|
||||
|
|
@ -368,7 +367,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::All(ns),
|
||||
parent_scope,
|
||||
finalize,
|
||||
finalize.is_some(),
|
||||
ignore_decl,
|
||||
None,
|
||||
)
|
||||
|
|
@ -396,12 +394,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
scope_set: ScopeSet<'ra>,
|
||||
parent_scope: &ParentScope<'ra>,
|
||||
finalize: Option<Finalize>,
|
||||
force: bool,
|
||||
ignore_decl: Option<Decl<'ra>>,
|
||||
ignore_import: Option<Import<'ra>>,
|
||||
) -> Result<Decl<'ra>, Determinacy> {
|
||||
assert!(force || finalize.is_none()); // `finalize` implies `force`
|
||||
|
||||
// Make sure `self`, `super` etc produce an error when passed to here.
|
||||
if !matches!(scope_set, ScopeSet::Module(..)) && orig_ident.is_path_segment_keyword() {
|
||||
return Err(Determinacy::Determined);
|
||||
|
|
@ -451,7 +446,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
parent_scope,
|
||||
// Shadowed decls don't need to be marked as used or non-speculatively loaded.
|
||||
if innermost_results.is_empty() { finalize } else { None },
|
||||
force,
|
||||
ignore_decl,
|
||||
ignore_import,
|
||||
) {
|
||||
|
|
@ -509,7 +503,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
// Scope visiting walked all the scopes and maybe found something in one of them.
|
||||
match innermost_results.first() {
|
||||
Some(&(decl, ..)) => Ok(decl),
|
||||
None => Err(Determinacy::determined(determinacy == Determinacy::Determined || force)),
|
||||
None => Err(determinacy),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -523,7 +517,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
scope_set: ScopeSet<'ra>,
|
||||
parent_scope: &ParentScope<'ra>,
|
||||
finalize: Option<Finalize>,
|
||||
force: bool,
|
||||
ignore_decl: Option<Decl<'ra>>,
|
||||
ignore_import: Option<Import<'ra>>,
|
||||
) -> Result<Decl<'ra>, ControlFlow<Determinacy, Determinacy>> {
|
||||
|
|
@ -546,7 +539,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
match self.reborrow().resolve_derive_macro_path(
|
||||
derive,
|
||||
parent_scope,
|
||||
force,
|
||||
false,
|
||||
ignore_import,
|
||||
) {
|
||||
Ok((Some(ext), _)) => {
|
||||
|
|
@ -617,11 +610,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
Ok(decl)
|
||||
}
|
||||
Err(ControlFlow::Continue(determinacy)) => Err(determinacy),
|
||||
Err(ControlFlow::Break(determinacy)) => {
|
||||
return Err(ControlFlow::Break(Determinacy::determined(
|
||||
determinacy == Determinacy::Determined || force,
|
||||
)));
|
||||
}
|
||||
Err(ControlFlow::Break(..)) => return decl,
|
||||
}
|
||||
}
|
||||
Scope::ModuleGlobs(module, derive_fallback_lint_id) => {
|
||||
|
|
@ -668,11 +657,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
Ok(binding)
|
||||
}
|
||||
Err(ControlFlow::Continue(determinacy)) => Err(determinacy),
|
||||
Err(ControlFlow::Break(determinacy)) => {
|
||||
return Err(ControlFlow::Break(Determinacy::determined(
|
||||
determinacy == Determinacy::Determined || force,
|
||||
)));
|
||||
}
|
||||
Err(ControlFlow::Break(..)) => return binding,
|
||||
}
|
||||
}
|
||||
Scope::MacroUsePrelude => match self.macro_use_prelude.get(&ident.name).cloned() {
|
||||
|
|
@ -715,7 +700,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::Module(ns, prelude),
|
||||
parent_scope,
|
||||
None,
|
||||
false,
|
||||
ignore_decl,
|
||||
ignore_import,
|
||||
)
|
||||
|
|
@ -951,7 +935,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::Module(ns, module),
|
||||
parent_scope,
|
||||
finalize,
|
||||
finalize.is_some(),
|
||||
ignore_decl,
|
||||
ignore_import,
|
||||
),
|
||||
|
|
@ -960,7 +943,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::ModuleAndExternPrelude(ns, module),
|
||||
parent_scope,
|
||||
finalize,
|
||||
finalize.is_some(),
|
||||
ignore_decl,
|
||||
ignore_import,
|
||||
),
|
||||
|
|
@ -973,7 +955,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::ExternPrelude,
|
||||
parent_scope,
|
||||
finalize,
|
||||
finalize.is_some(),
|
||||
ignore_decl,
|
||||
ignore_import,
|
||||
)
|
||||
|
|
@ -996,7 +977,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::All(ns),
|
||||
parent_scope,
|
||||
finalize,
|
||||
finalize.is_some(),
|
||||
ignore_decl,
|
||||
ignore_import,
|
||||
)
|
||||
|
|
@ -1180,7 +1160,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::Module(ns, module),
|
||||
adjusted_parent_scope,
|
||||
None,
|
||||
false,
|
||||
ignore_decl,
|
||||
ignore_import,
|
||||
);
|
||||
|
|
@ -1881,7 +1860,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::All(ns),
|
||||
parent_scope,
|
||||
finalize,
|
||||
finalize.is_some(),
|
||||
ignore_decl,
|
||||
ignore_import,
|
||||
)
|
||||
|
|
@ -1957,8 +1935,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
);
|
||||
}
|
||||
}
|
||||
Err(Undetermined) => return PathResult::Indeterminate,
|
||||
Err(Determined) => {
|
||||
Err(Undetermined) if finalize.is_none() => return PathResult::Indeterminate,
|
||||
Err(Determined | Undetermined) => {
|
||||
if let Some(ModuleOrUniformRoot::Module(module)) = module
|
||||
&& opt_ns.is_some()
|
||||
&& !module.is_normal()
|
||||
|
|
|
|||
|
|
@ -1498,7 +1498,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::All(ns),
|
||||
&import.parent_scope,
|
||||
None,
|
||||
false,
|
||||
decls[ns].get().decl(),
|
||||
None,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -799,10 +799,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::Macro(kind),
|
||||
parent_scope,
|
||||
None,
|
||||
force,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let binding = binding.map_err(|determinacy| {
|
||||
Determinacy::determined(determinacy == Determinacy::Determined || force)
|
||||
});
|
||||
if let Err(Determinacy::Undetermined) = binding {
|
||||
return Err(Determinacy::Undetermined);
|
||||
}
|
||||
|
|
@ -958,7 +960,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::Macro(kind),
|
||||
&parent_scope,
|
||||
Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)),
|
||||
true,
|
||||
None,
|
||||
None,
|
||||
) {
|
||||
|
|
@ -1013,7 +1014,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::Macro(MacroKind::Attr),
|
||||
&parent_scope,
|
||||
Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)),
|
||||
true,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
|
|
@ -1117,7 +1117,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ScopeSet::Macro(MacroKind::Bang),
|
||||
&ParentScope { macro_rules: no_macro_rules, ..*parent_scope },
|
||||
None,
|
||||
false,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1995,6 +1995,7 @@ symbols! {
|
|||
rustc_no_implicit_autorefs,
|
||||
rustc_no_implicit_bounds,
|
||||
rustc_no_mir_inline,
|
||||
rustc_non_const_trait_method,
|
||||
rustc_nonnull_optimization_guaranteed,
|
||||
rustc_nounwind,
|
||||
rustc_objc_class,
|
||||
|
|
|
|||
|
|
@ -279,7 +279,8 @@ pub trait FromIterator<A>: Sized {
|
|||
)]
|
||||
#[rustc_skip_during_method_dispatch(array, boxed_slice)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait IntoIterator {
|
||||
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
|
||||
pub const trait IntoIterator {
|
||||
/// The type of the elements being iterated over.
|
||||
#[rustc_diagnostic_item = "IntoIteratorItem"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
@ -312,7 +313,8 @@ pub trait IntoIterator {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I: Iterator> IntoIterator for I {
|
||||
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
|
||||
impl<I: [const] Iterator> const IntoIterator for I {
|
||||
type Item = I::Item;
|
||||
type IntoIter = I;
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,8 @@ fn _assert_is_dyn_compatible(_: &dyn Iterator<Item = ()>) {}
|
|||
#[lang = "iterator"]
|
||||
#[rustc_diagnostic_item = "Iterator"]
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
pub trait Iterator {
|
||||
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
|
||||
pub const trait Iterator {
|
||||
/// The type of the elements being iterated over.
|
||||
#[rustc_diagnostic_item = "IteratorItem"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
@ -107,6 +108,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "iter_next_chunk", issue = "98326")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn next_chunk<const N: usize>(
|
||||
&mut self,
|
||||
) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>>
|
||||
|
|
@ -219,6 +221,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn count(self) -> usize
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -251,6 +254,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn last(self) -> Option<Self::Item>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -298,6 +302,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "iter_advance_by", issue = "77404")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
|
||||
/// Helper trait to specialize `advance_by` via `try_fold` for `Sized` iterators.
|
||||
trait SpecAdvanceBy {
|
||||
|
|
@ -375,6 +380,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn nth(&mut self, n: usize) -> Option<Self::Item> {
|
||||
self.advance_by(n).ok()?;
|
||||
self.next()
|
||||
|
|
@ -425,6 +431,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iterator_step_by", since = "1.28.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn step_by(self, step: usize) -> StepBy<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -496,6 +503,7 @@ pub trait Iterator {
|
|||
/// [`OsStr`]: ../../std/ffi/struct.OsStr.html
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -614,6 +622,7 @@ pub trait Iterator {
|
|||
/// [`zip`]: crate::iter::zip
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -657,6 +666,7 @@ pub trait Iterator {
|
|||
/// [`intersperse_with`]: Iterator::intersperse_with
|
||||
#[inline]
|
||||
#[unstable(feature = "iter_intersperse", issue = "79524")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn intersperse(self, separator: Self::Item) -> Intersperse<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -715,6 +725,7 @@ pub trait Iterator {
|
|||
/// [`intersperse`]: Iterator::intersperse
|
||||
#[inline]
|
||||
#[unstable(feature = "iter_intersperse", issue = "79524")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -774,6 +785,7 @@ pub trait Iterator {
|
|||
#[rustc_diagnostic_item = "IteratorMap"]
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn map<B, F>(self, f: F) -> Map<Self, F>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -819,6 +831,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iterator_for_each", since = "1.21.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn for_each<F>(self, f: F)
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -894,6 +907,7 @@ pub trait Iterator {
|
|||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "iter_filter"]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn filter<P>(self, predicate: P) -> Filter<Self, P>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -939,6 +953,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -986,6 +1001,7 @@ pub trait Iterator {
|
|||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "enumerate_method"]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn enumerate(self) -> Enumerate<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -1057,6 +1073,7 @@ pub trait Iterator {
|
|||
/// [`next`]: Iterator::next
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn peekable(self) -> Peekable<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -1122,6 +1139,7 @@ pub trait Iterator {
|
|||
#[inline]
|
||||
#[doc(alias = "drop_while")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -1200,6 +1218,7 @@ pub trait Iterator {
|
|||
/// the iteration should stop, but wasn't placed back into the iterator.
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -1288,6 +1307,7 @@ pub trait Iterator {
|
|||
/// [`fuse`]: Iterator::fuse
|
||||
#[inline]
|
||||
#[stable(feature = "iter_map_while", since = "1.57.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -1317,6 +1337,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn skip(self, n: usize) -> Skip<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -1389,6 +1410,7 @@ pub trait Iterator {
|
|||
#[doc(alias = "limit")]
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn take(self, n: usize) -> Take<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -1436,6 +1458,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -1474,6 +1497,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -1558,6 +1582,7 @@ pub trait Iterator {
|
|||
/// [`flat_map()`]: Iterator::flat_map
|
||||
#[inline]
|
||||
#[stable(feature = "iterator_flatten", since = "1.29.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn flatten(self) -> Flatten<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -1714,6 +1739,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "iter_map_windows", issue = "87155")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn map_windows<F, R, const N: usize>(self, f: F) -> MapWindows<Self, F, N>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -1776,6 +1802,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn fuse(self) -> Fuse<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -1860,6 +1887,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn inspect<F>(self, f: F) -> Inspect<Self, F>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -2019,6 +2047,7 @@ pub trait Iterator {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"]
|
||||
#[rustc_diagnostic_item = "iterator_collect_fn"]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn collect<B: FromIterator<Self::Item>>(self) -> B
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -2106,6 +2135,7 @@ pub trait Iterator {
|
|||
/// [`collect`]: Iterator::collect
|
||||
#[inline]
|
||||
#[unstable(feature = "iterator_try_collect", issue = "94047")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn try_collect<B>(&mut self) -> ChangeOutputType<Self::Item, B>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -2178,6 +2208,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "iter_collect_into", issue = "94780")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn collect_into<E: Extend<Self::Item>>(self, collection: &mut E) -> &mut E
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -2210,6 +2241,7 @@ pub trait Iterator {
|
|||
/// assert_eq!(odd, [1, 3]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn partition<B, F>(self, f: F) -> (B, B)
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -2272,6 +2304,7 @@ pub trait Iterator {
|
|||
/// assert!(a[i..].iter().all(|n| n % 2 == 1)); // odds
|
||||
/// ```
|
||||
#[unstable(feature = "iter_partition_in_place", issue = "62543")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn partition_in_place<'a, T: 'a, P>(mut self, ref mut predicate: P) -> usize
|
||||
where
|
||||
Self: Sized + DoubleEndedIterator<Item = &'a mut T>,
|
||||
|
|
@ -2329,6 +2362,7 @@ pub trait Iterator {
|
|||
/// assert!(!"IntoIterator".chars().is_partitioned(char::is_uppercase));
|
||||
/// ```
|
||||
#[unstable(feature = "iter_is_partitioned", issue = "62544")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn is_partitioned<P>(mut self, mut predicate: P) -> bool
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -2423,6 +2457,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iterator_try_fold", since = "1.27.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -2481,6 +2516,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iterator_try_fold", since = "1.27.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn try_for_each<F, R>(&mut self, f: F) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -2600,6 +2636,7 @@ pub trait Iterator {
|
|||
#[doc(alias = "inject", alias = "foldl")]
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn fold<B, F>(mut self, init: B, mut f: F) -> B
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -2637,6 +2674,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iterator_fold_self", since = "1.51.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn reduce<F>(mut self, f: F) -> Option<Self::Item>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -2708,6 +2746,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "iterator_try_reduce", issue = "87053")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn try_reduce<R>(
|
||||
&mut self,
|
||||
f: impl FnMut(Self::Item, Self::Item) -> R,
|
||||
|
|
@ -2766,6 +2805,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn all<F>(&mut self, f: F) -> bool
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -2819,6 +2859,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn any<F>(&mut self, f: F) -> bool
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -2892,6 +2933,7 @@ pub trait Iterator {
|
|||
/// Note that `iter.find(f)` is equivalent to `iter.filter(f).next()`.
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -2923,6 +2965,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iterator_find_map", since = "1.30.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn find_map<B, F>(&mut self, f: F) -> Option<B>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -2981,6 +3024,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "try_find", issue = "63178")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn try_find<R>(
|
||||
&mut self,
|
||||
f: impl FnMut(&Self::Item) -> R,
|
||||
|
|
@ -3064,6 +3108,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn position<P>(&mut self, predicate: P) -> Option<usize>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -3129,6 +3174,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn rposition<P>(&mut self, predicate: P) -> Option<usize>
|
||||
where
|
||||
P: FnMut(Self::Item) -> bool,
|
||||
|
|
@ -3178,6 +3224,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn max(self) -> Option<Self::Item>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -3214,6 +3261,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn min(self) -> Option<Self::Item>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -3236,6 +3284,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iter_cmp_by_key", since = "1.6.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn max_by_key<B: Ord, F>(self, f: F) -> Option<Self::Item>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -3269,6 +3318,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iter_max_by", since = "1.15.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn max_by<F>(self, compare: F) -> Option<Self::Item>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -3296,6 +3346,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iter_cmp_by_key", since = "1.6.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn min_by_key<B: Ord, F>(self, f: F) -> Option<Self::Item>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -3329,6 +3380,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iter_min_by", since = "1.15.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn min_by<F>(self, compare: F) -> Option<Self::Item>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -3366,6 +3418,7 @@ pub trait Iterator {
|
|||
#[inline]
|
||||
#[doc(alias = "reverse")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn rev(self) -> Rev<Self>
|
||||
where
|
||||
Self: Sized + DoubleEndedIterator,
|
||||
|
|
@ -3402,6 +3455,7 @@ pub trait Iterator {
|
|||
/// assert_eq!(z, [3, 6]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)
|
||||
where
|
||||
FromA: Default + Extend<A>,
|
||||
|
|
@ -3433,6 +3487,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[stable(feature = "iter_copied", since = "1.36.0")]
|
||||
#[rustc_diagnostic_item = "iter_copied"]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn copied<'a, T>(self) -> Copied<Self>
|
||||
where
|
||||
T: Copy + 'a,
|
||||
|
|
@ -3481,6 +3536,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "iter_cloned"]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn cloned<'a, T>(self) -> Cloned<Self>
|
||||
where
|
||||
T: Clone + 'a,
|
||||
|
|
@ -3512,6 +3568,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn cycle(self) -> Cycle<Self>
|
||||
where
|
||||
Self: Sized + Clone,
|
||||
|
|
@ -3555,6 +3612,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[track_caller]
|
||||
#[unstable(feature = "iter_array_chunks", issue = "100450")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -3591,6 +3649,7 @@ pub trait Iterator {
|
|||
/// assert_eq!(sum, -0.0_f32);
|
||||
/// ```
|
||||
#[stable(feature = "iter_arith", since = "1.11.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn sum<S>(self) -> S
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -3623,6 +3682,7 @@ pub trait Iterator {
|
|||
/// assert_eq!(factorial(5), 120);
|
||||
/// ```
|
||||
#[stable(feature = "iter_arith", since = "1.11.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn product<P>(self) -> P
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -3644,6 +3704,7 @@ pub trait Iterator {
|
|||
/// assert_eq!([1, 2].iter().cmp([1].iter()), Ordering::Greater);
|
||||
/// ```
|
||||
#[stable(feature = "iter_order", since = "1.5.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn cmp<I>(self, other: I) -> Ordering
|
||||
where
|
||||
I: IntoIterator<Item = Self::Item>,
|
||||
|
|
@ -3671,6 +3732,7 @@ pub trait Iterator {
|
|||
/// assert_eq!(xs.into_iter().cmp_by(ys, |x, y| (2 * x).cmp(&y)), Ordering::Greater);
|
||||
/// ```
|
||||
#[unstable(feature = "iter_order_by", issue = "64295")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -3727,6 +3789,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
///
|
||||
#[stable(feature = "iter_order", since = "1.5.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn partial_cmp<I>(self, other: I) -> Option<Ordering>
|
||||
where
|
||||
I: IntoIterator,
|
||||
|
|
@ -3763,6 +3826,7 @@ pub trait Iterator {
|
|||
/// );
|
||||
/// ```
|
||||
#[unstable(feature = "iter_order_by", issue = "64295")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -3796,6 +3860,7 @@ pub trait Iterator {
|
|||
/// assert_eq!([1].iter().eq([1, 2].iter()), false);
|
||||
/// ```
|
||||
#[stable(feature = "iter_order", since = "1.5.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn eq<I>(self, other: I) -> bool
|
||||
where
|
||||
I: IntoIterator,
|
||||
|
|
@ -3819,6 +3884,7 @@ pub trait Iterator {
|
|||
/// assert!(xs.iter().eq_by(ys, |x, y| x * x == y));
|
||||
/// ```
|
||||
#[unstable(feature = "iter_order_by", issue = "64295")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn eq_by<I, F>(self, other: I, eq: F) -> bool
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -3848,6 +3914,7 @@ pub trait Iterator {
|
|||
/// assert_eq!([1].iter().ne([1, 2].iter()), true);
|
||||
/// ```
|
||||
#[stable(feature = "iter_order", since = "1.5.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn ne<I>(self, other: I) -> bool
|
||||
where
|
||||
I: IntoIterator,
|
||||
|
|
@ -3869,6 +3936,7 @@ pub trait Iterator {
|
|||
/// assert_eq!([1, 2].iter().lt([1, 2].iter()), false);
|
||||
/// ```
|
||||
#[stable(feature = "iter_order", since = "1.5.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn lt<I>(self, other: I) -> bool
|
||||
where
|
||||
I: IntoIterator,
|
||||
|
|
@ -3890,6 +3958,7 @@ pub trait Iterator {
|
|||
/// assert_eq!([1, 2].iter().le([1, 2].iter()), true);
|
||||
/// ```
|
||||
#[stable(feature = "iter_order", since = "1.5.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn le<I>(self, other: I) -> bool
|
||||
where
|
||||
I: IntoIterator,
|
||||
|
|
@ -3911,6 +3980,7 @@ pub trait Iterator {
|
|||
/// assert_eq!([1, 2].iter().gt([1, 2].iter()), false);
|
||||
/// ```
|
||||
#[stable(feature = "iter_order", since = "1.5.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn gt<I>(self, other: I) -> bool
|
||||
where
|
||||
I: IntoIterator,
|
||||
|
|
@ -3932,6 +4002,7 @@ pub trait Iterator {
|
|||
/// assert_eq!([1, 2].iter().ge([1, 2].iter()), true);
|
||||
/// ```
|
||||
#[stable(feature = "iter_order", since = "1.5.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn ge<I>(self, other: I) -> bool
|
||||
where
|
||||
I: IntoIterator,
|
||||
|
|
@ -3961,6 +4032,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "is_sorted", since = "1.82.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn is_sorted(self) -> bool
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -3987,6 +4059,7 @@ pub trait Iterator {
|
|||
/// assert!(std::iter::empty::<i32>().is_sorted_by(|a, b| true));
|
||||
/// ```
|
||||
#[stable(feature = "is_sorted", since = "1.82.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn is_sorted_by<F>(mut self, compare: F) -> bool
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -4031,6 +4104,7 @@ pub trait Iterator {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "is_sorted", since = "1.82.0")]
|
||||
#[rustc_non_const_trait_method]
|
||||
fn is_sorted_by_key<F, K>(self, f: F) -> bool
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
@ -4046,6 +4120,7 @@ pub trait Iterator {
|
|||
#[inline]
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
#[rustc_non_const_trait_method]
|
||||
unsafe fn __iterator_get_unchecked(&mut self, _idx: usize) -> Self::Item
|
||||
where
|
||||
Self: TrustedRandomAccessNoCoerce,
|
||||
|
|
|
|||
|
|
@ -2257,7 +2257,8 @@ impl<T> const Default for Option<T> {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> IntoIterator for Option<T> {
|
||||
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
|
||||
impl<T> const IntoIterator for Option<T> {
|
||||
type Item = T;
|
||||
type IntoIter = IntoIter<T>;
|
||||
|
||||
|
|
@ -2429,7 +2430,8 @@ struct Item<A> {
|
|||
opt: Option<A>,
|
||||
}
|
||||
|
||||
impl<A> Iterator for Item<A> {
|
||||
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
|
||||
impl<A> const Iterator for Item<A> {
|
||||
type Item = A;
|
||||
|
||||
#[inline]
|
||||
|
|
@ -2439,7 +2441,7 @@ impl<A> Iterator for Item<A> {
|
|||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let len = self.len();
|
||||
let len = self.opt.len();
|
||||
(len, Some(len))
|
||||
}
|
||||
}
|
||||
|
|
@ -2563,7 +2565,8 @@ pub struct IntoIter<A> {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A> Iterator for IntoIter<A> {
|
||||
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
|
||||
impl<A> const Iterator for IntoIter<A> {
|
||||
type Item = A;
|
||||
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -99,3 +99,18 @@ pub fn extend_for_unit() {
|
|||
}
|
||||
assert_eq!(x, 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_const_iter() {
|
||||
const X: bool = {
|
||||
let it = Some(42);
|
||||
let mut run = false;
|
||||
#[expect(for_loops_over_fallibles)]
|
||||
for x in it {
|
||||
assert!(x == 42);
|
||||
run = true;
|
||||
}
|
||||
run
|
||||
};
|
||||
assert_eq!(true, X);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#![feature(const_drop_in_place)]
|
||||
#![feature(const_eval_select)]
|
||||
#![feature(const_index)]
|
||||
#![feature(const_iter)]
|
||||
#![feature(const_ops)]
|
||||
#![feature(const_option_ops)]
|
||||
#![feature(const_ref_cell)]
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@
|
|||
- [Inference details](./opaque-types-impl-trait-inference.md)
|
||||
- [Return Position Impl Trait In Trait](./return-position-impl-trait-in-trait.md)
|
||||
- [Region inference restrictions](./borrow-check/opaque-types-region-inference-restrictions.md)
|
||||
- [Const condition checking](./effects.md)
|
||||
- [Const traits and const condition checking](./effects.md)
|
||||
- [Pattern and exhaustiveness checking](./pat-exhaustive-checking.md)
|
||||
- [Unsafety checking](./unsafety-checking.md)
|
||||
- [MIR dataflow](./mir/dataflow.md)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Effects and const condition checking
|
||||
# Effects, const traits, and const condition checking
|
||||
|
||||
## The `HostEffect` predicate
|
||||
|
||||
|
|
@ -154,3 +154,18 @@ be dropped at compile time.
|
|||
|
||||
[old solver]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_trait_selection/traits/effects.rs.html
|
||||
[new trait solver]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_next_trait_solver/solve/effect_goals.rs.html
|
||||
|
||||
## More on const traits
|
||||
|
||||
To be expanded later.
|
||||
|
||||
### The `#[rustc_non_const_trait_method]` attribute
|
||||
|
||||
This is intended for internal (standard library) usage only. With this attribute
|
||||
applied to a trait method, the compiler will not check the default body of this
|
||||
method for ability to run in compile time. Users of the trait will also not be
|
||||
allowed to use this trait method in const contexts. This attribute is primarily
|
||||
used for constifying large traits such as `Iterator` without having to make all
|
||||
its methods `const` at the same time.
|
||||
|
||||
This attribute should not be present while stabilizing the trait as `const`.
|
||||
|
|
|
|||
|
|
@ -5,5 +5,4 @@ macro_rules! sample { () => {} }
|
|||
#[sample] //~ ERROR cannot find attribute `sample` in this scope
|
||||
#[derive(sample)] //~ ERROR cannot find derive macro `sample` in this scope
|
||||
//~| ERROR cannot find derive macro `sample` in this scope
|
||||
//~| ERROR cannot find derive macro `sample` in this scope
|
||||
pub struct S {}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
error: cannot find derive macro `sample` in this scope
|
||||
--> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:6:10
|
||||
|
|
||||
LL | macro_rules! sample { () => {} }
|
||||
| ------ `sample` exists, but has no `derive` rules
|
||||
...
|
||||
LL | #[derive(sample)]
|
||||
| ^^^^^^
|
||||
|
||||
error: cannot find attribute `sample` in this scope
|
||||
--> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:5:3
|
||||
|
|
||||
|
|
@ -24,8 +15,6 @@ LL | macro_rules! sample { () => {} }
|
|||
...
|
||||
LL | #[derive(sample)]
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: cannot find derive macro `sample` in this scope
|
||||
--> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:6:10
|
||||
|
|
@ -38,5 +27,5 @@ LL | #[derive(sample)]
|
|||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
|||
7
tests/ui/traits/const-traits/partial/attr-gate.rs
Normal file
7
tests/ui/traits/const-traits/partial/attr-gate.rs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
trait A {
|
||||
#[rustc_non_const_trait_method]
|
||||
//~^ ERROR: use of an internal attribute
|
||||
fn a();
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
13
tests/ui/traits/const-traits/partial/attr-gate.stderr
Normal file
13
tests/ui/traits/const-traits/partial/attr-gate.stderr
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
error[E0658]: use of an internal attribute
|
||||
--> $DIR/attr-gate.rs:2:5
|
||||
|
|
||||
LL | #[rustc_non_const_trait_method]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
|
||||
= note: the `#[rustc_non_const_trait_method]` attribute is an internal implementation detail that will never be stable
|
||||
= note: `#[rustc_non_const_trait_method]` should only used by the standard library to mark trait methods as non-const to allow large traits an easier transition to const
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
39
tests/ui/traits/const-traits/partial/no-const-callers.rs
Normal file
39
tests/ui/traits/const-traits/partial/no-const-callers.rs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#![feature(const_trait_impl, rustc_attrs)]
|
||||
|
||||
const trait A {
|
||||
fn a();
|
||||
#[rustc_non_const_trait_method]
|
||||
fn b() { println!("hi"); }
|
||||
}
|
||||
|
||||
impl const A for () {
|
||||
fn a() {}
|
||||
}
|
||||
|
||||
impl const A for u8 {
|
||||
fn a() {}
|
||||
fn b() { println!("hello"); }
|
||||
//~^ ERROR: cannot call non-const function
|
||||
}
|
||||
|
||||
impl const A for i8 {
|
||||
fn a() {}
|
||||
fn b() {}
|
||||
}
|
||||
|
||||
const fn foo<T: [const] A>() {
|
||||
T::a();
|
||||
T::b();
|
||||
//~^ ERROR: cannot call non-const associated function
|
||||
<()>::a();
|
||||
<()>::b();
|
||||
//~^ ERROR: cannot call non-const associated function
|
||||
u8::a();
|
||||
u8::b();
|
||||
//~^ ERROR: cannot call non-const associated function
|
||||
i8::a();
|
||||
i8::b();
|
||||
//~^ ERROR: cannot call non-const associated function
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
45
tests/ui/traits/const-traits/partial/no-const-callers.stderr
Normal file
45
tests/ui/traits/const-traits/partial/no-const-callers.stderr
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
error[E0015]: cannot call non-const function `std::io::_print` in constant functions
|
||||
--> $DIR/no-const-callers.rs:15:14
|
||||
|
|
||||
LL | fn b() { println!("hello"); }
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: function `_print` is not const
|
||||
--> $SRC_DIR/std/src/io/stdio.rs:LL:COL
|
||||
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||
|
||||
error[E0015]: cannot call non-const associated function `<T as A>::b` in constant functions
|
||||
--> $DIR/no-const-callers.rs:26:5
|
||||
|
|
||||
LL | T::b();
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||
|
||||
error[E0015]: cannot call non-const associated function `<() as A>::b` in constant functions
|
||||
--> $DIR/no-const-callers.rs:29:5
|
||||
|
|
||||
LL | <()>::b();
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||
|
||||
error[E0015]: cannot call non-const associated function `<u8 as A>::b` in constant functions
|
||||
--> $DIR/no-const-callers.rs:32:5
|
||||
|
|
||||
LL | u8::b();
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||
|
||||
error[E0015]: cannot call non-const associated function `<i8 as A>::b` in constant functions
|
||||
--> $DIR/no-const-callers.rs:35:5
|
||||
|
|
||||
LL | i8::b();
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0015`.
|
||||
|
|
@ -684,13 +684,6 @@ error[E0015]: cannot call non-const method `<std::ops::Range<i32> as Iterator>::
|
|||
LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: method `filter` is not const because trait `Iterator` is not const
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
|
|
||||
= note: this trait is not const
|
||||
::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
|
|
||||
= note: this method is not const
|
||||
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
|
||||
|
||||
error[E0015]: cannot call non-const method `<Filter<std::ops::Range<i32>, {closure@$DIR/typeck_type_placeholder_item.rs:240:29: 240:32}> as Iterator>::map::<i32, {closure@$DIR/typeck_type_placeholder_item.rs:240:49: 240:52}>` in constants
|
||||
|
|
@ -699,13 +692,6 @@ error[E0015]: cannot call non-const method `<Filter<std::ops::Range<i32>, {closu
|
|||
LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: method `map` is not const because trait `Iterator` is not const
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
|
|
||||
= note: this trait is not const
|
||||
::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
|
|
||||
= note: this method is not const
|
||||
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
|
||||
|
||||
error: aborting due to 83 previous errors
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue