Rollup merge of #142801 - compiler-errors:gen-blocks, r=oli-obk
Use gen blocks in the compiler instead of `from_coroutine` r? oli-obk
This commit is contained in:
commit
6a49a35109
7 changed files with 139 additions and 154 deletions
|
|
@ -2177,84 +2177,80 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
/// Walk the generics of the item for a trait bound whose self type
|
||||
/// corresponds to the expected res, and return the trait def id.
|
||||
fn for_each_trait_bound_on_res(&self, expected_res: Res) -> impl Iterator<Item = DefId> {
|
||||
std::iter::from_coroutine(
|
||||
#[coroutine]
|
||||
move || {
|
||||
let mut scope = self.scope;
|
||||
loop {
|
||||
let hir_id = match *scope {
|
||||
Scope::Binder { hir_id, .. } => Some(hir_id),
|
||||
Scope::Root { opt_parent_item: Some(parent_def_id) } => {
|
||||
Some(self.tcx.local_def_id_to_hir_id(parent_def_id))
|
||||
}
|
||||
Scope::Body { .. }
|
||||
| Scope::ObjectLifetimeDefault { .. }
|
||||
| Scope::Supertrait { .. }
|
||||
| Scope::TraitRefBoundary { .. }
|
||||
| Scope::LateBoundary { .. }
|
||||
| Scope::Opaque { .. }
|
||||
| Scope::Root { opt_parent_item: None } => None,
|
||||
};
|
||||
gen move {
|
||||
let mut scope = self.scope;
|
||||
loop {
|
||||
let hir_id = match *scope {
|
||||
Scope::Binder { hir_id, .. } => Some(hir_id),
|
||||
Scope::Root { opt_parent_item: Some(parent_def_id) } => {
|
||||
Some(self.tcx.local_def_id_to_hir_id(parent_def_id))
|
||||
}
|
||||
Scope::Body { .. }
|
||||
| Scope::ObjectLifetimeDefault { .. }
|
||||
| Scope::Supertrait { .. }
|
||||
| Scope::TraitRefBoundary { .. }
|
||||
| Scope::LateBoundary { .. }
|
||||
| Scope::Opaque { .. }
|
||||
| Scope::Root { opt_parent_item: None } => None,
|
||||
};
|
||||
|
||||
if let Some(hir_id) = hir_id {
|
||||
let node = self.tcx.hir_node(hir_id);
|
||||
// If this is a `Self` bound in a trait, yield the trait itself.
|
||||
// Specifically, we don't need to look at any supertraits since
|
||||
// we already do that in `BoundVarContext::supertrait_hrtb_vars`.
|
||||
if let Res::SelfTyParam { trait_: _ } = expected_res
|
||||
&& let hir::Node::Item(item) = node
|
||||
&& let hir::ItemKind::Trait(..) = item.kind
|
||||
{
|
||||
// Yield the trait's def id. Supertraits will be
|
||||
// elaborated from that.
|
||||
yield item.owner_id.def_id.to_def_id();
|
||||
} else if let Some(generics) = node.generics() {
|
||||
for pred in generics.predicates {
|
||||
let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) =
|
||||
pred.bounded_ty.kind
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
// Match the expected res.
|
||||
if bounded_path.res != expected_res {
|
||||
continue;
|
||||
}
|
||||
for pred in pred.bounds {
|
||||
match pred {
|
||||
hir::GenericBound::Trait(poly_trait_ref) => {
|
||||
if let Some(def_id) =
|
||||
poly_trait_ref.trait_ref.trait_def_id()
|
||||
{
|
||||
yield def_id;
|
||||
}
|
||||
if let Some(hir_id) = hir_id {
|
||||
let node = self.tcx.hir_node(hir_id);
|
||||
// If this is a `Self` bound in a trait, yield the trait itself.
|
||||
// Specifically, we don't need to look at any supertraits since
|
||||
// we already do that in `BoundVarContext::supertrait_hrtb_vars`.
|
||||
if let Res::SelfTyParam { trait_: _ } = expected_res
|
||||
&& let hir::Node::Item(item) = node
|
||||
&& let hir::ItemKind::Trait(..) = item.kind
|
||||
{
|
||||
// Yield the trait's def id. Supertraits will be
|
||||
// elaborated from that.
|
||||
yield item.owner_id.def_id.to_def_id();
|
||||
} else if let Some(generics) = node.generics() {
|
||||
for pred in generics.predicates {
|
||||
let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind else {
|
||||
continue;
|
||||
};
|
||||
let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) =
|
||||
pred.bounded_ty.kind
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
// Match the expected res.
|
||||
if bounded_path.res != expected_res {
|
||||
continue;
|
||||
}
|
||||
for pred in pred.bounds {
|
||||
match pred {
|
||||
hir::GenericBound::Trait(poly_trait_ref) => {
|
||||
if let Some(def_id) =
|
||||
poly_trait_ref.trait_ref.trait_def_id()
|
||||
{
|
||||
yield def_id;
|
||||
}
|
||||
hir::GenericBound::Outlives(_)
|
||||
| hir::GenericBound::Use(_, _) => {}
|
||||
}
|
||||
hir::GenericBound::Outlives(_)
|
||||
| hir::GenericBound::Use(_, _) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match *scope {
|
||||
Scope::Binder { s, .. }
|
||||
| Scope::Body { s, .. }
|
||||
| Scope::ObjectLifetimeDefault { s, .. }
|
||||
| Scope::Supertrait { s, .. }
|
||||
| Scope::TraitRefBoundary { s }
|
||||
| Scope::LateBoundary { s, .. }
|
||||
| Scope::Opaque { s, .. } => {
|
||||
scope = s;
|
||||
}
|
||||
Scope::Root { .. } => break,
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
match *scope {
|
||||
Scope::Binder { s, .. }
|
||||
| Scope::Body { s, .. }
|
||||
| Scope::ObjectLifetimeDefault { s, .. }
|
||||
| Scope::Supertrait { s, .. }
|
||||
| Scope::TraitRefBoundary { s }
|
||||
| Scope::LateBoundary { s, .. }
|
||||
| Scope::Opaque { s, .. } => {
|
||||
scope = s;
|
||||
}
|
||||
Scope::Root { .. } => break,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@ This API is completely unstable and subject to change.
|
|||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(coroutines)]
|
||||
#![feature(debug_closure_helpers)]
|
||||
#![feature(gen_blocks)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(iter_from_coroutine)]
|
||||
#![feature(iter_intersperse)]
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
#![allow(internal_features)]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(coroutines)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(error_iter)]
|
||||
#![feature(file_buffered)]
|
||||
#![feature(gen_blocks)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(iter_from_coroutine)]
|
||||
#![feature(macro_metavar_expr)]
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
use std::iter::TrustedLen;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::{Arc, OnceLock};
|
||||
use std::{io, iter, mem};
|
||||
use std::{io, mem};
|
||||
|
||||
pub(super) use cstore_impl::provide;
|
||||
use rustc_ast as ast;
|
||||
|
|
@ -1272,34 +1272,30 @@ impl<'a> CrateMetadataRef<'a> {
|
|||
id: DefIndex,
|
||||
sess: &'a Session,
|
||||
) -> impl Iterator<Item = ModChild> {
|
||||
iter::from_coroutine(
|
||||
#[coroutine]
|
||||
move || {
|
||||
if let Some(data) = &self.root.proc_macro_data {
|
||||
// If we are loading as a proc macro, we want to return
|
||||
// the view of this crate as a proc macro crate.
|
||||
if id == CRATE_DEF_INDEX {
|
||||
for child_index in data.macros.decode(self) {
|
||||
yield self.get_mod_child(child_index, sess);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Iterate over all children.
|
||||
let non_reexports =
|
||||
self.root.tables.module_children_non_reexports.get(self, id);
|
||||
for child_index in non_reexports.unwrap().decode(self) {
|
||||
gen move {
|
||||
if let Some(data) = &self.root.proc_macro_data {
|
||||
// If we are loading as a proc macro, we want to return
|
||||
// the view of this crate as a proc macro crate.
|
||||
if id == CRATE_DEF_INDEX {
|
||||
for child_index in data.macros.decode(self) {
|
||||
yield self.get_mod_child(child_index, sess);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Iterate over all children.
|
||||
let non_reexports = self.root.tables.module_children_non_reexports.get(self, id);
|
||||
for child_index in non_reexports.unwrap().decode(self) {
|
||||
yield self.get_mod_child(child_index, sess);
|
||||
}
|
||||
|
||||
let reexports = self.root.tables.module_children_reexports.get(self, id);
|
||||
if !reexports.is_default() {
|
||||
for reexport in reexports.decode((self, sess)) {
|
||||
yield reexport;
|
||||
}
|
||||
let reexports = self.root.tables.module_children_reexports.get(self, id);
|
||||
if !reexports.is_default() {
|
||||
for reexport in reexports.decode((self, sess)) {
|
||||
yield reexport;
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_ctfe_mir_available(self, id: DefIndex) -> bool {
|
||||
|
|
|
|||
|
|
@ -40,12 +40,12 @@
|
|||
#![feature(box_patterns)]
|
||||
#![feature(closure_track_caller)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(coroutines)]
|
||||
#![feature(debug_closure_helpers)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(discriminant_kind)]
|
||||
#![feature(extern_types)]
|
||||
#![feature(file_buffered)]
|
||||
#![feature(gen_blocks)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(intra_doc_pointers)]
|
||||
#![feature(iter_from_coroutine)]
|
||||
|
|
|
|||
|
|
@ -422,53 +422,49 @@ pub fn analyze_coroutine_closure_captures<'a, 'tcx: 'a, T>(
|
|||
child_captures: impl IntoIterator<Item = &'a CapturedPlace<'tcx>>,
|
||||
mut for_each: impl FnMut((usize, &'a CapturedPlace<'tcx>), (usize, &'a CapturedPlace<'tcx>)) -> T,
|
||||
) -> impl Iterator<Item = T> {
|
||||
std::iter::from_coroutine(
|
||||
#[coroutine]
|
||||
move || {
|
||||
let mut child_captures = child_captures.into_iter().enumerate().peekable();
|
||||
gen move {
|
||||
let mut child_captures = child_captures.into_iter().enumerate().peekable();
|
||||
|
||||
// One parent capture may correspond to several child captures if we end up
|
||||
// refining the set of captures via edition-2021 precise captures. We want to
|
||||
// match up any number of child captures with one parent capture, so we keep
|
||||
// peeking off this `Peekable` until the child doesn't match anymore.
|
||||
for (parent_field_idx, parent_capture) in parent_captures.into_iter().enumerate() {
|
||||
// Make sure we use every field at least once, b/c why are we capturing something
|
||||
// if it's not used in the inner coroutine.
|
||||
let mut field_used_at_least_once = false;
|
||||
// One parent capture may correspond to several child captures if we end up
|
||||
// refining the set of captures via edition-2021 precise captures. We want to
|
||||
// match up any number of child captures with one parent capture, so we keep
|
||||
// peeking off this `Peekable` until the child doesn't match anymore.
|
||||
for (parent_field_idx, parent_capture) in parent_captures.into_iter().enumerate() {
|
||||
// Make sure we use every field at least once, b/c why are we capturing something
|
||||
// if it's not used in the inner coroutine.
|
||||
let mut field_used_at_least_once = false;
|
||||
|
||||
// A parent matches a child if they share the same prefix of projections.
|
||||
// The child may have more, if it is capturing sub-fields out of
|
||||
// something that is captured by-move in the parent closure.
|
||||
while child_captures.peek().is_some_and(|(_, child_capture)| {
|
||||
child_prefix_matches_parent_projections(parent_capture, child_capture)
|
||||
}) {
|
||||
let (child_field_idx, child_capture) = child_captures.next().unwrap();
|
||||
// This analysis only makes sense if the parent capture is a
|
||||
// prefix of the child capture.
|
||||
assert!(
|
||||
child_capture.place.projections.len()
|
||||
>= parent_capture.place.projections.len(),
|
||||
"parent capture ({parent_capture:#?}) expected to be prefix of \
|
||||
child capture ({child_capture:#?})"
|
||||
);
|
||||
|
||||
yield for_each(
|
||||
(parent_field_idx, parent_capture),
|
||||
(child_field_idx, child_capture),
|
||||
);
|
||||
|
||||
field_used_at_least_once = true;
|
||||
}
|
||||
|
||||
// Make sure the field was used at least once.
|
||||
// A parent matches a child if they share the same prefix of projections.
|
||||
// The child may have more, if it is capturing sub-fields out of
|
||||
// something that is captured by-move in the parent closure.
|
||||
while child_captures.peek().is_some_and(|(_, child_capture)| {
|
||||
child_prefix_matches_parent_projections(parent_capture, child_capture)
|
||||
}) {
|
||||
let (child_field_idx, child_capture) = child_captures.next().unwrap();
|
||||
// This analysis only makes sense if the parent capture is a
|
||||
// prefix of the child capture.
|
||||
assert!(
|
||||
field_used_at_least_once,
|
||||
"we captured {parent_capture:#?} but it was not used in the child coroutine?"
|
||||
child_capture.place.projections.len() >= parent_capture.place.projections.len(),
|
||||
"parent capture ({parent_capture:#?}) expected to be prefix of \
|
||||
child capture ({child_capture:#?})"
|
||||
);
|
||||
|
||||
yield for_each(
|
||||
(parent_field_idx, parent_capture),
|
||||
(child_field_idx, child_capture),
|
||||
);
|
||||
|
||||
field_used_at_least_once = true;
|
||||
}
|
||||
assert_eq!(child_captures.next(), None, "leftover child captures?");
|
||||
},
|
||||
)
|
||||
|
||||
// Make sure the field was used at least once.
|
||||
assert!(
|
||||
field_used_at_least_once,
|
||||
"we captured {parent_capture:#?} but it was not used in the child coroutine?"
|
||||
);
|
||||
}
|
||||
assert_eq!(child_captures.next(), None, "leftover child captures?");
|
||||
}
|
||||
}
|
||||
|
||||
fn child_prefix_matches_parent_projections(
|
||||
|
|
|
|||
|
|
@ -2087,23 +2087,20 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
|
||||
|
||||
let definitions = &self.untracked.definitions;
|
||||
std::iter::from_coroutine(
|
||||
#[coroutine]
|
||||
|| {
|
||||
let mut i = 0;
|
||||
gen {
|
||||
let mut i = 0;
|
||||
|
||||
// Recompute the number of definitions each time, because our caller may be creating
|
||||
// new ones.
|
||||
while i < { definitions.read().num_definitions() } {
|
||||
let local_def_index = rustc_span::def_id::DefIndex::from_usize(i);
|
||||
yield LocalDefId { local_def_index };
|
||||
i += 1;
|
||||
}
|
||||
// Recompute the number of definitions each time, because our caller may be creating
|
||||
// new ones.
|
||||
while i < { definitions.read().num_definitions() } {
|
||||
let local_def_index = rustc_span::def_id::DefIndex::from_usize(i);
|
||||
yield LocalDefId { local_def_index };
|
||||
i += 1;
|
||||
}
|
||||
|
||||
// Freeze definitions once we finish iterating on them, to prevent adding new ones.
|
||||
definitions.freeze();
|
||||
},
|
||||
)
|
||||
// Freeze definitions once we finish iterating on them, to prevent adding new ones.
|
||||
definitions.freeze();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue