Skip to content

Commit 3c85538

Browse files
authored
Unrolled build for rust-lang#122829
Rollup merge of rust-lang#122829 - ShoyuVanilla:gen-block-impl-fused-iter, r=compiler-errors Implement `FusedIterator` for `gen` block cc rust-lang#117078
2 parents 0ad927c + ae4c5c8 commit 3c85538

File tree

10 files changed

+105
-7
lines changed

10 files changed

+105
-7
lines changed

compiler/rustc_hir/src/lang_items.rs

+1
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ language_item_table! {
214214
FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None;
215215

216216
Iterator, sym::iterator, iterator_trait, Target::Trait, GenericRequirement::Exact(0);
217+
FusedIterator, sym::fused_iterator, fused_iterator_trait, Target::Trait, GenericRequirement::Exact(0);
217218
Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0);
218219
AsyncIterator, sym::async_iterator, async_iterator_trait, Target::Trait, GenericRequirement::Exact(0);
219220

compiler/rustc_span/src/symbol.rs

+2
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ symbols! {
207207
FromResidual,
208208
FsOpenOptions,
209209
FsPermissions,
210+
FusedIterator,
210211
Future,
211212
FutureOutput,
212213
GlobalAlloc,
@@ -886,6 +887,7 @@ symbols! {
886887
fsub_algebraic,
887888
fsub_fast,
888889
fundamental,
890+
fused_iterator,
889891
future,
890892
future_trait,
891893
gdb_script_file,

compiler/rustc_trait_selection/src/solve/assembly/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,13 @@ pub(super) trait GoalKind<'tcx>:
215215
goal: Goal<'tcx, Self>,
216216
) -> QueryResult<'tcx>;
217217

218+
/// A coroutine (that comes from a `gen` desugaring) is known to implement
219+
/// `FusedIterator`
220+
fn consider_builtin_fused_iterator_candidate(
221+
ecx: &mut EvalCtxt<'_, 'tcx>,
222+
goal: Goal<'tcx, Self>,
223+
) -> QueryResult<'tcx>;
224+
218225
fn consider_builtin_async_iterator_candidate(
219226
ecx: &mut EvalCtxt<'_, 'tcx>,
220227
goal: Goal<'tcx, Self>,
@@ -497,6 +504,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
497504
G::consider_builtin_future_candidate(self, goal)
498505
} else if lang_items.iterator_trait() == Some(trait_def_id) {
499506
G::consider_builtin_iterator_candidate(self, goal)
507+
} else if lang_items.fused_iterator_trait() == Some(trait_def_id) {
508+
G::consider_builtin_fused_iterator_candidate(self, goal)
500509
} else if lang_items.async_iterator_trait() == Some(trait_def_id) {
501510
G::consider_builtin_async_iterator_candidate(self, goal)
502511
} else if lang_items.coroutine_trait() == Some(trait_def_id) {

compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
647647
)
648648
}
649649

650+
fn consider_builtin_fused_iterator_candidate(
651+
_ecx: &mut EvalCtxt<'_, 'tcx>,
652+
goal: Goal<'tcx, Self>,
653+
) -> QueryResult<'tcx> {
654+
bug!("`FusedIterator` does not have an associated type: {:?}", goal);
655+
}
656+
650657
fn consider_builtin_async_iterator_candidate(
651658
ecx: &mut EvalCtxt<'_, 'tcx>,
652659
goal: Goal<'tcx, Self>,

compiler/rustc_trait_selection/src/solve/trait_goals.rs

+22
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,28 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
456456
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
457457
}
458458

459+
fn consider_builtin_fused_iterator_candidate(
460+
ecx: &mut EvalCtxt<'_, 'tcx>,
461+
goal: Goal<'tcx, Self>,
462+
) -> QueryResult<'tcx> {
463+
if goal.predicate.polarity != ty::ImplPolarity::Positive {
464+
return Err(NoSolution);
465+
}
466+
467+
let ty::Coroutine(def_id, _) = *goal.predicate.self_ty().kind() else {
468+
return Err(NoSolution);
469+
};
470+
471+
// Coroutines are not iterators unless they come from `gen` desugaring
472+
let tcx = ecx.tcx();
473+
if !tcx.coroutine_is_gen(def_id) {
474+
return Err(NoSolution);
475+
}
476+
477+
// Gen coroutines unconditionally implement `FusedIterator`
478+
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
479+
}
480+
459481
fn consider_builtin_async_iterator_candidate(
460482
ecx: &mut EvalCtxt<'_, 'tcx>,
461483
goal: Goal<'tcx, Self>,

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

+26-7
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
118118
self.assemble_future_candidates(obligation, &mut candidates);
119119
} else if lang_items.iterator_trait() == Some(def_id) {
120120
self.assemble_iterator_candidates(obligation, &mut candidates);
121+
} else if lang_items.fused_iterator_trait() == Some(def_id) {
122+
self.assemble_fused_iterator_candidates(obligation, &mut candidates);
121123
} else if lang_items.async_iterator_trait() == Some(def_id) {
122124
self.assemble_async_iterator_candidates(obligation, &mut candidates);
123125
} else if lang_items.async_fn_kind_helper() == Some(def_id) {
@@ -302,14 +304,31 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
302304
candidates: &mut SelectionCandidateSet<'tcx>,
303305
) {
304306
let self_ty = obligation.self_ty().skip_binder();
305-
if let ty::Coroutine(did, ..) = self_ty.kind() {
306-
// gen constructs get lowered to a special kind of coroutine that
307-
// should directly `impl Iterator`.
308-
if self.tcx().coroutine_is_gen(*did) {
309-
debug!(?self_ty, ?obligation, "assemble_iterator_candidates",);
307+
// gen constructs get lowered to a special kind of coroutine that
308+
// should directly `impl Iterator`.
309+
if let ty::Coroutine(did, ..) = self_ty.kind()
310+
&& self.tcx().coroutine_is_gen(*did)
311+
{
312+
debug!(?self_ty, ?obligation, "assemble_iterator_candidates",);
310313

311-
candidates.vec.push(IteratorCandidate);
312-
}
314+
candidates.vec.push(IteratorCandidate);
315+
}
316+
}
317+
318+
fn assemble_fused_iterator_candidates(
319+
&mut self,
320+
obligation: &PolyTraitObligation<'tcx>,
321+
candidates: &mut SelectionCandidateSet<'tcx>,
322+
) {
323+
let self_ty = obligation.self_ty().skip_binder();
324+
// gen constructs get lowered to a special kind of coroutine that
325+
// should directly `impl FusedIterator`.
326+
if let ty::Coroutine(did, ..) = self_ty.kind()
327+
&& self.tcx().coroutine_is_gen(*did)
328+
{
329+
debug!(?self_ty, ?obligation, "assemble_fused_iterator_candidates",);
330+
331+
candidates.vec.push(BuiltinCandidate { has_nested: false });
313332
}
314333
}
315334

compiler/rustc_trait_selection/src/traits/select/confirmation.rs

+2
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
267267
self.copy_clone_conditions(obligation)
268268
} else if Some(trait_def) == lang_items.clone_trait() {
269269
self.copy_clone_conditions(obligation)
270+
} else if Some(trait_def) == lang_items.fused_iterator_trait() {
271+
self.fused_iterator_conditions(obligation)
270272
} else {
271273
bug!("unexpected builtin trait {:?}", trait_def)
272274
};

compiler/rustc_trait_selection/src/traits/select/mod.rs

+14
Original file line numberDiff line numberDiff line change
@@ -2259,6 +2259,20 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
22592259
}
22602260
}
22612261

2262+
fn fused_iterator_conditions(
2263+
&mut self,
2264+
obligation: &PolyTraitObligation<'tcx>,
2265+
) -> BuiltinImplConditions<'tcx> {
2266+
let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
2267+
if let ty::Coroutine(did, ..) = *self_ty.kind()
2268+
&& self.tcx().coroutine_is_gen(did)
2269+
{
2270+
BuiltinImplConditions::Where(ty::Binder::dummy(Vec::new()))
2271+
} else {
2272+
BuiltinImplConditions::None
2273+
}
2274+
}
2275+
22622276
/// For default impls, we need to break apart a type into its
22632277
/// "constituent types" -- meaning, the types that it contains.
22642278
///

library/core/src/iter/traits/marker.rs

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub unsafe trait TrustedFused {}
2828
#[rustc_unsafe_specialization_marker]
2929
// FIXME: this should be a #[marker] and have another blanket impl for T: TrustedFused
3030
// but that ICEs iter::Fuse specializations.
31+
#[cfg_attr(not(bootstrap), lang = "fused_iterator")]
3132
pub trait FusedIterator: Iterator {}
3233

3334
#[stable(feature = "fused", since = "1.26.0")]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//@ revisions: next old
2+
//@compile-flags: --edition 2024 -Zunstable-options
3+
//@[next] compile-flags: -Znext-solver
4+
//@ check-pass
5+
#![feature(gen_blocks)]
6+
7+
use std::iter::FusedIterator;
8+
9+
fn foo() -> impl FusedIterator {
10+
gen { yield 42 }
11+
}
12+
13+
fn bar() -> impl FusedIterator<Item = u16> {
14+
gen { yield 42 }
15+
}
16+
17+
fn baz() -> impl FusedIterator + Iterator<Item = i64> {
18+
gen { yield 42 }
19+
}
20+
21+
fn main() {}

0 commit comments

Comments
 (0)