Skip to content

Commit a23c3e3

Browse files
committed
Generator go brrr
1 parent 77652b9 commit a23c3e3

File tree

14 files changed

+169
-18
lines changed

14 files changed

+169
-18
lines changed

Cargo.lock

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2949,9 +2949,8 @@ dependencies = [
29492949

29502950
[[package]]
29512951
name = "psm"
2952-
version = "0.1.16"
2953-
source = "registry+https://github.com/rust-lang/crates.io-index"
2954-
checksum = "cd136ff4382c4753fc061cb9e4712ab2af263376b95bbd5bd8cd50c020b78e69"
2952+
version = "0.1.18"
2953+
source = "git+https://github.com/nbdd0121/stacker.git#eae7e163f2286071b4abb3c2ba85ad6632df848d"
29552954
dependencies = [
29562955
"cc",
29572956
]
@@ -4496,6 +4495,7 @@ dependencies = [
44964495
"rustc_trait_selection",
44974496
"rustc_ty_utils",
44984497
"smallvec",
4498+
"stackful",
44994499
"tracing",
45004500
]
45014501

@@ -4896,8 +4896,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
48964896
[[package]]
48974897
name = "stacker"
48984898
version = "0.1.14"
4899-
source = "registry+https://github.com/rust-lang/crates.io-index"
4900-
checksum = "90939d5171a4420b3ff5fbc8954d641e7377335454c259dcb80786f3f21dc9b4"
4899+
source = "git+https://github.com/nbdd0121/stacker.git#eae7e163f2286071b4abb3c2ba85ad6632df848d"
49014900
dependencies = [
49024901
"cc",
49034902
"cfg-if 1.0.0",
@@ -4906,6 +4905,16 @@ dependencies = [
49064905
"winapi",
49074906
]
49084907

4908+
[[package]]
4909+
name = "stackful"
4910+
version = "0.1.3"
4911+
source = "git+https://github.com/nbdd0121/stackful.git?branch=dev#5fedf72a244f7581bb10d063ae89919636b86ea1"
4912+
dependencies = [
4913+
"cc",
4914+
"libc",
4915+
"stacker",
4916+
]
4917+
49094918
[[package]]
49104919
name = "static_assertions"
49114920
version = "1.1.0"

compiler/rustc_data_structures/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ rustc_index = { path = "../rustc_index", package = "rustc_index" }
2525
bitflags = "1.2.1"
2626
measureme = "10.0.0"
2727
libc = "0.2"
28-
stacker = "0.1.14"
28+
stacker = { git = "https://github.com/nbdd0121/stacker.git" }
2929
tempfile = "3.2"
3030

3131
[dependencies.parking_lot]

compiler/rustc_middle/src/arena.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ macro_rules! arena_types {
102102
[decode] impl_source: rustc_middle::traits::ImplSource<'tcx, ()>,
103103

104104
[] dep_kind: rustc_middle::dep_graph::DepKindStruct,
105+
106+
[] steal_typeck_generator: rustc_data_structures::steal::Steal<rustc_middle::ty::TypeckResultGenerator<'tcx>>,
105107
]);
106108
)
107109
}

compiler/rustc_middle/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
#![feature(decl_macro)]
6060
#![feature(drain_filter)]
6161
#![feature(intra_doc_pointers)]
62+
#![feature(generator_trait)]
6263
#![recursion_limit = "512"]
6364
#![allow(rustc::potential_query_instability)]
6465

compiler/rustc_middle/src/query/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,14 @@ rustc_queries! {
808808
desc { "type-checking all item bodies" }
809809
}
810810

811+
query typeck_generator(key: (LocalDefId, u32)) -> (
812+
&'tcx Steal<ty::TypeckResultGenerator<'tcx>>,
813+
std::ops::GeneratorState<(LocalDefId, DefId), &'tcx ty::TypeckResults<'tcx>>,
814+
) {
815+
no_hash
816+
desc { |tcx| "type-checking `{}`, step {}", tcx.def_path_str(key.0.to_def_id()), key.1 }
817+
}
818+
811819
query typeck(key: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> {
812820
desc { |tcx| "type-checking `{}`", tcx.def_path_str(key.to_def_id()) }
813821
cache_on_disk_if { true }

compiler/rustc_middle/src/ty/context.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,25 @@ pub struct GeneratorDiagnosticData<'tcx> {
377377
pub adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
378378
}
379379

380+
pub struct TypeckResultGenerator<'tcx>(
381+
pub std::mem::ManuallyDrop<
382+
std::pin::Pin<
383+
Box<
384+
dyn std::ops::Generator<
385+
Yield = (LocalDefId, DefId),
386+
Return = &'tcx TypeckResults<'tcx>,
387+
> + 'tcx,
388+
>,
389+
>,
390+
>,
391+
);
392+
393+
impl fmt::Debug for TypeckResultGenerator<'_> {
394+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
395+
f.debug_tuple("TypeckResultGenerator").finish()
396+
}
397+
}
398+
380399
#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
381400
pub struct TypeckResults<'tcx> {
382401
/// The `HirId::owner` all `ItemLocalId`s in this table are relative to.

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ pub use self::consts::{
6868
pub use self::context::{
6969
tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
7070
CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorDiagnosticData,
71-
GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TypeckResults, UserType,
72-
UserTypeAnnotationIndex,
71+
GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TypeckResultGenerator,
72+
TypeckResults, UserType, UserTypeAnnotationIndex,
7373
};
7474
pub use self::instance::{Instance, InstanceDef};
7575
pub use self::list::List;

compiler/rustc_query_impl/src/keys.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,3 +513,16 @@ impl<'tcx> Key for (Ty<'tcx>, ty::ValTree<'tcx>) {
513513
DUMMY_SP
514514
}
515515
}
516+
517+
impl Key for (LocalDefId, u32) {
518+
#[inline(always)]
519+
fn query_crate_is_local(&self) -> bool {
520+
true
521+
}
522+
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
523+
self.0.to_def_id().default_span(tcx)
524+
}
525+
fn key_as_def_id(&self) -> Option<DefId> {
526+
Some(self.0.to_def_id())
527+
}
528+
}

compiler/rustc_typeck/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,4 @@ rustc_trait_selection = { path = "../rustc_trait_selection" }
2929
rustc_ty_utils = { path = "../rustc_ty_utils" }
3030
rustc_lint = { path = "../rustc_lint" }
3131
rustc_serialize = { path = "../rustc_serialize" }
32+
stackful = { git = "https://github.com/nbdd0121/stackful.git", branch = "dev", default-features = false, features = ["nightly"] }

compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
537537
did: self.tcx.hir().local_def_id(ast_c.hir_id),
538538
const_param_did: Some(param_def_id),
539539
};
540+
541+
if let Some(y) = self.yield_handle {
542+
y.yeet((const_def.did, param_def_id));
543+
}
544+
540545
let c = ty::Const::from_opt_const_arg_anon_const(self.tcx, const_def);
541546
self.register_wf_obligation(
542547
c.into(),

compiler/rustc_typeck/src/check/inherited.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use super::MaybeInProgressTables;
33

44
use rustc_data_structures::fx::FxHashSet;
55
use rustc_hir as hir;
6-
use rustc_hir::def_id::{DefIdMap, LocalDefId};
6+
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
77
use rustc_hir::HirIdMap;
88
use rustc_infer::infer;
99
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
@@ -59,6 +59,8 @@ pub struct Inherited<'a, 'tcx> {
5959
/// we record that type variable here. This is later used to inform
6060
/// fallback. See the `fallback` module for details.
6161
pub(super) diverging_type_vars: RefCell<FxHashSet<Ty<'tcx>>>,
62+
63+
pub(super) yield_handle: Option<&'a stackful::generator::YieldHandle<(LocalDefId, DefId)>>,
6264
}
6365

6466
impl<'a, 'tcx> Deref for Inherited<'a, 'tcx> {
@@ -95,10 +97,26 @@ impl<'tcx> InheritedBuilder<'tcx> {
9597
let def_id = self.def_id;
9698
self.infcx.enter(|infcx| f(Inherited::new(infcx, def_id)))
9799
}
100+
101+
pub fn enter_with_yield_handle<F, R>(
102+
&mut self,
103+
yield_handle: Option<&stackful::generator::YieldHandle<(LocalDefId, DefId)>>,
104+
f: F,
105+
) -> R
106+
where
107+
F: for<'a> FnOnce(Inherited<'a, 'tcx>) -> R,
108+
{
109+
let def_id = self.def_id;
110+
self.infcx.enter(|infcx| f(Inherited::new_with_yield_handle(infcx, def_id, yield_handle)))
111+
}
98112
}
99113

100114
impl<'a, 'tcx> Inherited<'a, 'tcx> {
101-
pub(super) fn new(infcx: InferCtxt<'a, 'tcx>, def_id: LocalDefId) -> Self {
115+
pub(super) fn new_with_yield_handle(
116+
infcx: InferCtxt<'a, 'tcx>,
117+
def_id: LocalDefId,
118+
yield_handle: Option<&'a stackful::generator::YieldHandle<(LocalDefId, DefId)>>,
119+
) -> Self {
102120
let tcx = infcx.tcx;
103121
let item_id = tcx.hir().local_def_id_to_hir_id(def_id);
104122
let body_id = tcx.hir().maybe_body_owned_by(item_id);
@@ -116,9 +134,14 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
116134
deferred_generator_interiors: RefCell::new(Vec::new()),
117135
diverging_type_vars: RefCell::new(Default::default()),
118136
body_id,
137+
yield_handle,
119138
}
120139
}
121140

141+
pub(super) fn new(infcx: InferCtxt<'a, 'tcx>, def_id: LocalDefId) -> Self {
142+
Self::new_with_yield_handle(infcx, def_id, None)
143+
}
144+
122145
#[instrument(level = "debug", skip(self))]
123146
pub(super) fn register_predicate(&self, obligation: traits::PredicateObligation<'tcx>) {
124147
if obligation.has_escaping_bound_vars() {

compiler/rustc_typeck/src/check/mod.rs

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ pub use inherited::{Inherited, InheritedBuilder};
104104
use crate::astconv::AstConv;
105105
use crate::check::gather_locals::GatherLocalsVisitor;
106106
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
107+
use rustc_data_structures::steal::Steal;
107108
use rustc_errors::{
108109
pluralize, struct_span_err, Applicability, DiagnosticBuilder, EmissionGuarantee, MultiSpan,
109110
};
@@ -132,6 +133,7 @@ use rustc_trait_selection::traits::error_reporting::recursive_type_with_infinite
132133
use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
133134

134135
use std::cell::{Ref, RefCell, RefMut};
136+
use std::ops::{Generator, GeneratorState};
135137

136138
use crate::require_c_abi_if_c_variadic;
137139
use crate::util::common::indenter;
@@ -244,6 +246,7 @@ pub fn provide(providers: &mut Providers) {
244246
method::provide(providers);
245247
*providers = Providers {
246248
typeck_item_bodies,
249+
typeck_generator,
247250
typeck_const_arg,
248251
typeck,
249252
diagnostic_only_typeck,
@@ -319,20 +322,57 @@ fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &FxHashSet<LocalDe
319322
&*tcx.typeck(def_id).used_trait_imports
320323
}
321324

325+
fn typeck_generator<'tcx>(
326+
tcx: TyCtxt<'tcx>,
327+
(def_id, step): (LocalDefId, u32),
328+
) -> (
329+
&'tcx Steal<ty::TypeckResultGenerator<'tcx>>,
330+
GeneratorState<(LocalDefId, DefId), &'tcx ty::TypeckResults<'tcx>>,
331+
) {
332+
use std::mem::ManuallyDrop;
333+
334+
let mut gen = if step == 0 {
335+
ty::TypeckResultGenerator(ManuallyDrop::new(Box::pin(
336+
stackful::generator::StackfulGenerator::new(move |y, ()| {
337+
let fallback = move || tcx.type_of(def_id.to_def_id());
338+
typeck_with_fallback(tcx, def_id, fallback, Some(y))
339+
}),
340+
)))
341+
} else {
342+
tcx.typeck_generator((def_id, step - 1)).0.steal()
343+
};
344+
345+
let state = std::pin::Pin::new(&mut *gen.0).resume(());
346+
let steal = tcx.arena.alloc(Steal::new(gen));
347+
if let GeneratorState::Complete(_) = state {
348+
drop(ManuallyDrop::into_inner(steal.steal().0));
349+
}
350+
(steal, state)
351+
}
352+
322353
fn typeck_const_arg<'tcx>(
323354
tcx: TyCtxt<'tcx>,
324355
(did, param_did): (LocalDefId, DefId),
325356
) -> &ty::TypeckResults<'tcx> {
326357
let fallback = move || tcx.type_of(param_did);
327-
typeck_with_fallback(tcx, did, fallback)
358+
typeck_with_fallback(tcx, did, fallback, None)
328359
}
329360

330361
fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
331362
if let Some(param_did) = tcx.opt_const_param_of(def_id) {
332363
tcx.typeck_const_arg((def_id, param_did))
333364
} else {
334-
let fallback = move || tcx.type_of(def_id.to_def_id());
335-
typeck_with_fallback(tcx, def_id, fallback)
365+
let mut step = 0;
366+
loop {
367+
match tcx.typeck_generator((def_id, step)).1 {
368+
GeneratorState::Yielded(y) => {
369+
// eprintln!(">>> {:?}", y);
370+
let _ = y;
371+
}
372+
GeneratorState::Complete(v) => break v,
373+
}
374+
step += 1;
375+
}
336376
}
337377
}
338378

@@ -343,14 +383,15 @@ fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::T
343383
let span = tcx.hir().span(tcx.hir().local_def_id_to_hir_id(def_id));
344384
tcx.ty_error_with_message(span, "diagnostic only typeck table used")
345385
};
346-
typeck_with_fallback(tcx, def_id, fallback)
386+
typeck_with_fallback(tcx, def_id, fallback, None)
347387
}
348388

349-
#[instrument(skip(tcx, fallback))]
389+
#[instrument(skip(tcx, fallback, yield_handle))]
350390
fn typeck_with_fallback<'tcx>(
351391
tcx: TyCtxt<'tcx>,
352392
def_id: LocalDefId,
353393
fallback: impl Fn() -> Ty<'tcx> + 'tcx,
394+
yield_handle: Option<&stackful::generator::YieldHandle<(LocalDefId, DefId)>>,
354395
) -> &'tcx ty::TypeckResults<'tcx> {
355396
// Closures' typeck results come from their outermost function,
356397
// as they are part of the same "inference environment".
@@ -368,7 +409,7 @@ fn typeck_with_fallback<'tcx>(
368409
});
369410
let body = tcx.hir().body(body_id);
370411

371-
let typeck_results = Inherited::build(tcx, def_id).enter(|inh| {
412+
let typeck_results = Inherited::build(tcx, def_id).enter_with_yield_handle(yield_handle, |inh| {
372413
let param_env = tcx.param_env(def_id);
373414
let (fcx, wf_tys) = if let Some(hir::FnSig { header, decl, .. }) = fn_sig {
374415
let fn_sig = if crate::collect::get_infer_ret_ty(&decl.output).is_some() {

compiler/rustc_typeck/src/collect/type_of.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,21 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
100100
..
101101
}) => {
102102
let body_owner = tcx.hir().local_def_id(tcx.hir().enclosing_body_owner(hir_id));
103-
let tables = tcx.typeck(body_owner);
103+
104+
let mut step = 0;
105+
let tables = loop {
106+
use std::ops::GeneratorState;
107+
match tcx.typeck_generator((body_owner, step)).1 {
108+
GeneratorState::Yielded((const_did, const_param)) => {
109+
if const_did == def_id {
110+
return Some(const_param);
111+
}
112+
}
113+
GeneratorState::Complete(v) => break v,
114+
}
115+
step += 1;
116+
};
117+
104118
// This may fail in case the method/path does not actually exist.
105119
// As there is no relevant param for `def_id`, we simply return
106120
// `None` here.
@@ -134,7 +148,21 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
134148
..
135149
}) => {
136150
let body_owner = tcx.hir().local_def_id(tcx.hir().enclosing_body_owner(hir_id));
137-
let _tables = tcx.typeck(body_owner);
151+
152+
let mut step = 0;
153+
loop {
154+
use std::ops::GeneratorState;
155+
match tcx.typeck_generator((body_owner, step)).1 {
156+
GeneratorState::Yielded((const_did, _)) => {
157+
if const_did == def_id {
158+
break;
159+
}
160+
}
161+
GeneratorState::Complete(_) => break,
162+
}
163+
step += 1;
164+
}
165+
138166
&*path
139167
}
140168
Node::Pat(pat) => {

compiler/rustc_typeck/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ This API is completely unstable and subject to change.
7373
#![feature(once_cell)]
7474
#![feature(slice_partition_dedup)]
7575
#![feature(try_blocks)]
76+
#![feature(generator_trait)]
7677
#![recursion_limit = "256"]
7778

7879
#[macro_use]

0 commit comments

Comments
 (0)