Skip to content

Commit 75121fc

Browse files
committed
Separate generator info from MIR body.
1 parent 0568b0a commit 75121fc

34 files changed

+282
-735
lines changed

compiler/rustc_borrowck/src/type_check/input_output.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -115,28 +115,26 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
115115
}
116116
}
117117

118+
let body_yield_ty = body.yield_ty(self.tcx());
118119
debug!(
119120
"equate_inputs_and_outputs: body.yield_ty {:?}, universal_regions.yield_ty {:?}",
120-
body.yield_ty(),
121-
universal_regions.yield_ty
121+
body_yield_ty, universal_regions.yield_ty
122122
);
123123

124124
// We will not have a universal_regions.yield_ty if we yield (by accident)
125125
// outside of a generator and return an `impl Trait`, so emit a delay_span_bug
126126
// because we don't want to panic in an assert here if we've already got errors.
127-
if body.yield_ty().is_some() != universal_regions.yield_ty.is_some() {
127+
if body_yield_ty.is_some() != universal_regions.yield_ty.is_some() {
128128
self.tcx().sess.delay_span_bug(
129129
body.span,
130130
&format!(
131131
"Expected body to have yield_ty ({:?}) iff we have a UR yield_ty ({:?})",
132-
body.yield_ty(),
133-
universal_regions.yield_ty,
132+
body_yield_ty, universal_regions.yield_ty,
134133
),
135134
);
136135
}
137136

138-
if let (Some(mir_yield_ty), Some(ur_yield_ty)) =
139-
(body.yield_ty(), universal_regions.yield_ty)
137+
if let (Some(mir_yield_ty), Some(ur_yield_ty)) = (body_yield_ty, universal_regions.yield_ty)
140138
{
141139
let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
142140
self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty, yield_span);

compiler/rustc_borrowck/src/type_check/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1473,7 +1473,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
14731473
self.check_operand(value, term_location);
14741474

14751475
let value_ty = value.ty(body, tcx);
1476-
match body.yield_ty() {
1476+
match body.yield_ty(tcx) {
14771477
None => span_mirbug!(self, term, "yield in non-generator"),
14781478
Some(ty) => {
14791479
if let Err(terr) = self.sub_types(

compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1235,8 +1235,8 @@ fn generator_layout_and_saved_local_names<'tcx>(
12351235
tcx: TyCtxt<'tcx>,
12361236
def_id: DefId,
12371237
) -> (&'tcx GeneratorLayout<'tcx>, IndexVec<mir::GeneratorSavedLocal, Option<Symbol>>) {
1238+
let generator_layout = &tcx.mir_generator_info(def_id).generator_layout;
12381239
let body = tcx.optimized_mir(def_id);
1239-
let generator_layout = body.generator_layout().unwrap();
12401240
let mut generator_saved_local_names = IndexVec::from_elem(None, &generator_layout.field_tys);
12411241

12421242
let state_arg = mir::Local::new(1);

compiler/rustc_const_eval/src/transform/check_consts/check.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
222222

223223
// `async` functions cannot be `const fn`. This is checked during AST lowering, so there's
224224
// no need to emit duplicate errors here.
225-
if self.ccx.is_async() || body.generator.is_some() {
225+
if self.ccx.is_async() || tcx.generator_kind(def_id).is_some() {
226226
tcx.sess.delay_span_bug(body.span, "`async` functions cannot be `const fn`");
227227
return;
228228
}

compiler/rustc_const_eval/src/transform/promote_consts.rs

-1
Original file line numberDiff line numberDiff line change
@@ -973,7 +973,6 @@ pub fn promote_candidates<'tcx>(
973973
0,
974974
vec![],
975975
body.span,
976-
body.generator_kind(),
977976
body.tainted_by_errors,
978977
);
979978
promoted.phase = MirPhase::Analysis(AnalysisPhase::Initial);

compiler/rustc_const_eval/src/transform/validate.rs

+8-14
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ impl<'tcx> MirPass<'tcx> for Validator {
6565
storage_liveness,
6666
place_cache: Vec::new(),
6767
value_cache: Vec::new(),
68+
is_generator: tcx.generator_kind(def_id).is_some(),
6869
}
6970
.visit_body(body);
7071
}
@@ -117,6 +118,7 @@ struct TypeChecker<'a, 'tcx> {
117118
storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive>,
118119
place_cache: Vec<PlaceRef<'tcx>>,
119120
value_cache: Vec<u128>,
121+
is_generator: bool,
120122
}
121123

122124
impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
@@ -323,16 +325,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
323325
}
324326
&ty::Generator(def_id, substs, _) => {
325327
let f_ty = if let Some(var) = parent_ty.variant_index {
326-
let gen_body = if def_id == self.body.source.def_id() {
327-
self.body
328-
} else {
329-
self.tcx.optimized_mir(def_id)
330-
};
331-
332-
let Some(layout) = gen_body.generator_layout() else {
333-
self.fail(location, format!("No generator layout for {:?}", parent_ty));
334-
return;
335-
};
328+
let generator_info = self.tcx.mir_generator_info(def_id);
329+
let layout = &generator_info.generator_layout;
336330

337331
let Some(&local) = layout.variant_fields[var].get(f) else {
338332
fail_out_of_bounds(self, location);
@@ -836,10 +830,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
836830
}
837831
}
838832
TerminatorKind::Yield { resume, drop, .. } => {
839-
if self.body.generator.is_none() {
833+
if !self.is_generator {
840834
self.fail(location, "`Yield` cannot appear outside generator bodies");
841835
}
842-
if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
836+
if self.mir_phase >= MirPhase::Runtime(RuntimePhase::GeneratorsLowered) {
843837
self.fail(location, "`Yield` should have been replaced by generator lowering");
844838
}
845839
self.check_edge(location, *resume, EdgeKind::Normal);
@@ -878,10 +872,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
878872
}
879873
}
880874
TerminatorKind::GeneratorDrop => {
881-
if self.body.generator.is_none() {
875+
if !self.is_generator {
882876
self.fail(location, "`GeneratorDrop` cannot appear outside generator bodies");
883877
}
884-
if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
878+
if self.mir_phase >= MirPhase::Runtime(RuntimePhase::GeneratorsLowered) {
885879
self.fail(
886880
location,
887881
"`GeneratorDrop` should have been replaced by generator lowering",

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+1
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ provide! { tcx, def_id, other, cdata,
203203
thir_abstract_const => { table }
204204
optimized_mir => { table }
205205
mir_for_ctfe => { table }
206+
mir_generator_info => { table }
206207
promoted_mir => { table }
207208
def_span => { table }
208209
def_ident_span => { table }

compiler/rustc_metadata/src/rmeta/encoder.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1387,6 +1387,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
13871387
debug!("EntryBuilder::encode_mir({:?})", def_id);
13881388
if encode_opt {
13891389
record!(self.tables.optimized_mir[def_id.to_def_id()] <- tcx.optimized_mir(def_id));
1390+
1391+
if let DefKind::Generator = self.tcx.def_kind(def_id) {
1392+
record!(self.tables.mir_generator_info[def_id.to_def_id()] <- tcx.mir_generator_info(def_id));
1393+
}
13901394
}
13911395
if encode_const {
13921396
record!(self.tables.mir_for_ctfe[def_id.to_def_id()] <- tcx.mir_for_ctfe(def_id));

compiler/rustc_metadata/src/rmeta/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ define_tables! {
361361
object_lifetime_default: Table<DefIndex, LazyValue<ObjectLifetimeDefault>>,
362362
optimized_mir: Table<DefIndex, LazyValue<mir::Body<'static>>>,
363363
mir_for_ctfe: Table<DefIndex, LazyValue<mir::Body<'static>>>,
364+
mir_generator_info: Table<DefIndex, LazyValue<mir::GeneratorInfo<'static>>>,
364365
promoted_mir: Table<DefIndex, LazyValue<IndexVec<mir::Promoted, mir::Body<'static>>>>,
365366
// FIXME(compiler-errors): Why isn't this a LazyArray?
366367
thir_abstract_const: Table<DefIndex, LazyValue<&'static [ty::abstract_const::Node<'static>]>>,

compiler/rustc_middle/src/arena.rs

+5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ macro_rules! arena_types {
1313
[] steal_thir: rustc_data_structures::steal::Steal<rustc_middle::thir::Thir<'tcx>>,
1414
[] steal_mir: rustc_data_structures::steal::Steal<rustc_middle::mir::Body<'tcx>>,
1515
[decode] mir: rustc_middle::mir::Body<'tcx>,
16+
[decode] generator_info: rustc_middle::mir::GeneratorInfo<'tcx>,
17+
[] mir_generator_lowered: (
18+
rustc_data_structures::steal::Steal<rustc_middle::mir::Body<'tcx>>,
19+
Option<rustc_middle::mir::GeneratorInfo<'tcx>>,
20+
),
1621
[] steal_promoted:
1722
rustc_data_structures::steal::Steal<
1823
rustc_index::vec::IndexVec<

compiler/rustc_middle/src/mir/mod.rs

+11-39
Original file line numberDiff line numberDiff line change
@@ -179,18 +179,11 @@ impl<'tcx> MirSource<'tcx> {
179179

180180
#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)]
181181
pub struct GeneratorInfo<'tcx> {
182-
/// The yield type of the function, if it is a generator.
183-
pub yield_ty: Option<Ty<'tcx>>,
184-
185182
/// Generator drop glue.
186-
pub generator_drop: Option<Body<'tcx>>,
183+
pub generator_drop: Body<'tcx>,
187184

188185
/// The layout of a generator. Produced by the state transformation.
189-
pub generator_layout: Option<GeneratorLayout<'tcx>>,
190-
191-
/// If this is a generator then record the type of source expression that caused this generator
192-
/// to be created.
193-
pub generator_kind: GeneratorKind,
186+
pub generator_layout: GeneratorLayout<'tcx>,
194187
}
195188

196189
/// The lowered representation of a single function.
@@ -213,8 +206,6 @@ pub struct Body<'tcx> {
213206
/// and used for debuginfo. Indexed by a `SourceScope`.
214207
pub source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
215208

216-
pub generator: Option<Box<GeneratorInfo<'tcx>>>,
217-
218209
/// Declarations of locals.
219210
///
220211
/// The first local is the return value pointer, followed by `arg_count`
@@ -279,7 +270,6 @@ impl<'tcx> Body<'tcx> {
279270
arg_count: usize,
280271
var_debug_info: Vec<VarDebugInfo<'tcx>>,
281272
span: Span,
282-
generator_kind: Option<GeneratorKind>,
283273
tainted_by_errors: Option<ErrorGuaranteed>,
284274
) -> Self {
285275
// We need `arg_count` locals, and one for the return place.
@@ -295,14 +285,6 @@ impl<'tcx> Body<'tcx> {
295285
source,
296286
basic_blocks: BasicBlocks::new(basic_blocks),
297287
source_scopes,
298-
generator: generator_kind.map(|generator_kind| {
299-
Box::new(GeneratorInfo {
300-
yield_ty: None,
301-
generator_drop: None,
302-
generator_layout: None,
303-
generator_kind,
304-
})
305-
}),
306288
local_decls,
307289
user_type_annotations,
308290
arg_count,
@@ -328,7 +310,6 @@ impl<'tcx> Body<'tcx> {
328310
source: MirSource::item(CRATE_DEF_ID.to_def_id()),
329311
basic_blocks: BasicBlocks::new(basic_blocks),
330312
source_scopes: IndexVec::new(),
331-
generator: None,
332313
local_decls: IndexVec::new(),
333314
user_type_annotations: IndexVec::new(),
334315
arg_count: 0,
@@ -460,24 +441,15 @@ impl<'tcx> Body<'tcx> {
460441
.unwrap_or_else(|| Either::Right(block_data.terminator()))
461442
}
462443

463-
#[inline]
464-
pub fn yield_ty(&self) -> Option<Ty<'tcx>> {
465-
self.generator.as_ref().and_then(|generator| generator.yield_ty)
466-
}
467-
468-
#[inline]
469-
pub fn generator_layout(&self) -> Option<&GeneratorLayout<'tcx>> {
470-
self.generator.as_ref().and_then(|generator| generator.generator_layout.as_ref())
471-
}
472-
473-
#[inline]
474-
pub fn generator_drop(&self) -> Option<&Body<'tcx>> {
475-
self.generator.as_ref().and_then(|generator| generator.generator_drop.as_ref())
476-
}
477-
478-
#[inline]
479-
pub fn generator_kind(&self) -> Option<GeneratorKind> {
480-
self.generator.as_ref().map(|generator| generator.generator_kind)
444+
pub fn yield_ty(&self, tcx: TyCtxt<'_>) -> Option<Ty<'tcx>> {
445+
if tcx.generator_kind(self.source.def_id()).is_none() {
446+
return None;
447+
};
448+
let gen_ty = self.local_decls.raw[1].ty;
449+
match *gen_ty.kind() {
450+
ty::Generator(_, substs, _) => Some(substs.as_generator().sig().yield_ty),
451+
_ => None,
452+
}
481453
}
482454
}
483455

compiler/rustc_middle/src/mir/pretty.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,10 @@ fn dump_matched_mir_node<'tcx, F>(
131131
Some(promoted) => write!(file, "::{:?}`", promoted)?,
132132
}
133133
writeln!(file, " {} {}", disambiguator, pass_name)?;
134-
if let Some(ref layout) = body.generator_layout() {
134+
// Trying to fetch the layout before it has been computed would create a query cycle.
135+
if body.phase >= MirPhase::Runtime(RuntimePhase::GeneratorsLowered)
136+
&& let Some(layout) = tcx.generator_layout(body.source.def_id())
137+
{
135138
writeln!(file, "/* generator_layout = {:#?} */", layout)?;
136139
}
137140
writeln!(file)?;
@@ -1003,7 +1006,7 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn Write) -> io::Res
10031006
write!(w, ": {} =", body.return_ty())?;
10041007
}
10051008

1006-
if let Some(yield_ty) = body.yield_ty() {
1009+
if let Some(yield_ty) = body.yield_ty(tcx) {
10071010
writeln!(w)?;
10081011
writeln!(w, "yields {}", yield_ty)?;
10091012
}

compiler/rustc_middle/src/mir/syntax.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,6 @@ pub enum RuntimePhase {
112112
/// In addition to the semantic changes, beginning with this phase, the following variants are
113113
/// disallowed:
114114
/// * [`TerminatorKind::DropAndReplace`]
115-
/// * [`TerminatorKind::Yield`]
116-
/// * [`TerminatorKind::GeneratorDrop`]
117115
/// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array`
118116
///
119117
/// And the following variants are allowed:
@@ -126,7 +124,13 @@ pub enum RuntimePhase {
126124
/// Beginning with this phase, the following variant is disallowed:
127125
/// * [`ProjectionElem::Deref`] of `Box`
128126
PostCleanup = 1,
129-
Optimized = 2,
127+
/// Beginning with this phase, the following variant is disallowed:
128+
/// * [`TerminatorKind::Yield`]
129+
/// * [`TerminatorKind::GeneratorDrop`]
130+
///
131+
/// Furthermore, `Copy` operands are allowed for non-`Copy` types.
132+
GeneratorsLowered = 2,
133+
Optimized = 3,
130134
}
131135

132136
///////////////////////////////////////////////////////////////////////////

compiler/rustc_middle/src/mir/visit.rs

-10
Original file line numberDiff line numberDiff line change
@@ -979,16 +979,6 @@ macro_rules! extra_body_methods {
979979

980980
macro_rules! super_body {
981981
($self:ident, $body:ident, $($mutability:ident, $invalidate:tt)?) => {
982-
let span = $body.span;
983-
if let Some(gen) = &$($mutability)? $body.generator {
984-
if let Some(yield_ty) = $(& $mutability)? gen.yield_ty {
985-
$self.visit_ty(
986-
yield_ty,
987-
TyContext::YieldTy(SourceInfo::outermost(span))
988-
);
989-
}
990-
}
991-
992982
for (bb, data) in basic_blocks_iter!($body, $($mutability, $invalidate)?) {
993983
$self.visit_basic_block_data(bb, data);
994984
}

compiler/rustc_middle/src/query/mod.rs

+15
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,21 @@ rustc_queries! {
423423
}
424424
}
425425

426+
query mir_generator_lowered(key: LocalDefId) -> &'tcx (
427+
Steal<mir::Body<'tcx>>,
428+
Option<mir::GeneratorInfo<'tcx>>,
429+
430+
) {
431+
no_hash
432+
desc { |tcx| "computing generator MIR for `{}`", tcx.def_path_str(key.to_def_id()) }
433+
}
434+
435+
query mir_generator_info(key: DefId) -> &'tcx mir::GeneratorInfo<'tcx> {
436+
desc { |tcx| "generator glue MIR for `{}`", tcx.def_path_str(key) }
437+
cache_on_disk_if { key.is_local() }
438+
separate_provide_extern
439+
}
440+
426441
/// MIR after our optimization passes have run. This is MIR that is ready
427442
/// for codegen. This is also the only query that can fetch non-local MIR, at present.
428443
query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> {

compiler/rustc_middle/src/ty/codec.rs

+1
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ impl_decodable_via_ref! {
381381
&'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>,
382382
&'tcx traits::ImplSource<'tcx, ()>,
383383
&'tcx mir::Body<'tcx>,
384+
&'tcx mir::GeneratorInfo<'tcx>,
384385
&'tcx mir::UnsafetyCheckResult,
385386
&'tcx mir::BorrowCheckResult<'tcx>,
386387
&'tcx mir::coverage::CodeRegion,

compiler/rustc_middle/src/ty/mod.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -2291,7 +2291,11 @@ impl<'tcx> TyCtxt<'tcx> {
22912291
/// Returns layout of a generator. Layout might be unavailable if the
22922292
/// generator is tainted by errors.
22932293
pub fn generator_layout(self, def_id: DefId) -> Option<&'tcx GeneratorLayout<'tcx>> {
2294-
self.optimized_mir(def_id).generator_layout()
2294+
if self.generator_kind(def_id).is_some() {
2295+
Some(&self.mir_generator_info(def_id).generator_layout)
2296+
} else {
2297+
None
2298+
}
22952299
}
22962300

22972301
/// Given the `DefId` of an impl, returns the `DefId` of the trait it implements.

compiler/rustc_middle/src/ty/parameterized.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use rustc_hir::def_id::DefId;
22
use rustc_index::vec::{Idx, IndexVec};
33

44
use crate::middle::exported_symbols::ExportedSymbol;
5-
use crate::mir::Body;
5+
use crate::mir::{Body, GeneratorInfo};
66
use crate::ty::abstract_const::Node;
77
use crate::ty::{
88
self, Const, FnSig, GeneratorDiagnosticData, GenericPredicates, Predicate, TraitRef, Ty,
@@ -117,6 +117,7 @@ parameterized_over_tcx! {
117117
Predicate,
118118
GeneratorDiagnosticData,
119119
Body,
120+
GeneratorInfo,
120121
Node,
121122
ExportedSymbol,
122123
}

0 commit comments

Comments
 (0)