Skip to content

Commit 1c6ef1d

Browse files
committed
Implement generators
`GeneratorDatum` and `GeneratorWitnessDatum` are introduced, which mirror `TyKind::Generator` and `TyKind::GeneratorWitness` in rustc. We handle auto traits for `GeneratorDatum` using the existing `constituent_types` method. For `GeneratorWitnessDatum`, we generate a `forall<'a, 'b, ... 'z>` goal to reflect the fact that our lifetimes are existentially bound. Unresolved questions: * The implementation of `GeneratorWitnessDatum` needs careful review - I'm not certain that I fully understand how `Binders` works. * The syntax implemented in `parser.lalrpop` can be bikesheeded. We might want to use something other than `for<>` for the witness types, to reflect that fact that we have existential rather than universal quantification. * The generator grammar only allows quantifying over liftimes for the witness types - however, this gets lowered to a `Binders`, which supports types and constants as well. Should we do anything else to ensure we never end up with types/consts where they're not expected? * I added a test to ensure that we treat the witness lifetimes as existentially quantified - for example, if we have `for<'a, 'b> Foo<'a, 'b>`, we should only be able to use an auto trait impl that is fully generic over lifetimes - e.g. `impl<'a> Send for Foo<'a, 'b>` will not be used. I *believe* that the test is showing this behavior - it ends up returning region constraints that require `'a` and `'b` to outlive each other. Since these are 'existential' lifetimes (which cannot be substituted), this is an unsatisfiable constraint. However, I'm not sure where we should be detecting that this is unsatisfiable.
1 parent ea42560 commit 1c6ef1d

File tree

29 files changed

+585
-18
lines changed

29 files changed

+585
-18
lines changed

chalk-integration/src/db.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ use crate::{
88
};
99
use chalk_ir::{
1010
AdtId, ApplicationTy, AssocTypeId, Binders, Canonical, CanonicalVarKinds, ClosureId,
11-
ConstrainedSubst, Environment, FnDefId, GenericArg, Goal, ImplId, InEnvironment, OpaqueTyId,
12-
ProgramClause, ProgramClauses, Substitution, TraitId, Ty, UCanonical,
11+
ConstrainedSubst, Environment, FnDefId, GeneratorId, GenericArg, Goal, ImplId, InEnvironment,
12+
OpaqueTyId, ProgramClause, ProgramClauses, Substitution, TraitId, Ty, UCanonical,
1313
};
1414
use chalk_solve::rust_ir::{
1515
AdtDatum, AdtRepr, AssociatedTyDatum, AssociatedTyValue, AssociatedTyValueId, ClosureKind,
16-
FnDefDatum, FnDefInputsAndOutputDatum, ImplDatum, OpaqueTyDatum, TraitDatum, WellKnownTrait,
16+
FnDefDatum, FnDefInputsAndOutputDatum, GeneratorDatum, GeneratorWitnessDatum, ImplDatum,
17+
OpaqueTyDatum, TraitDatum, WellKnownTrait,
1718
};
1819
use chalk_solve::{RustIrDatabase, Solution, SubstitutionResult};
1920
use salsa::Database;
@@ -106,6 +107,17 @@ impl RustIrDatabase<ChalkIr> for ChalkDatabase {
106107
self.program_ir().unwrap().adt_datum(id)
107108
}
108109

110+
fn generator_datum(&self, id: GeneratorId<ChalkIr>) -> Arc<GeneratorDatum<ChalkIr>> {
111+
self.program_ir().unwrap().generator_datum(id)
112+
}
113+
114+
fn generator_witness_datum(
115+
&self,
116+
id: GeneratorId<ChalkIr>,
117+
) -> Arc<GeneratorWitnessDatum<ChalkIr>> {
118+
self.program_ir().unwrap().generator_witness_datum(id)
119+
}
120+
109121
fn adt_repr(&self, id: AdtId<ChalkIr>) -> AdtRepr {
110122
self.program_ir().unwrap().adt_repr(id)
111123
}

chalk-integration/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub enum TypeSort {
2727
Closure,
2828
Trait,
2929
Opaque,
30+
Generator,
3031
}
3132

3233
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]

chalk-integration/src/lowering.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ mod env;
22
mod program_lowerer;
33

44
use chalk_ir::cast::{Cast, Caster};
5+
56
use chalk_ir::{
67
self, BoundVar, ClausePriority, DebruijnIndex, ImplId, QuantifiedWhereClauses, Substitution,
78
TyKind,
@@ -78,6 +79,21 @@ trait LowerParameterMap {
7879
// as an object. Actually the handling of object types is
7980
// probably just kind of messed up right now. That's ok.
8081
}
82+
83+
fn parameter_map(&self) -> ParameterMap {
84+
self.all_parameters()
85+
.into_iter()
86+
.zip((0..).map(|i| BoundVar::new(DebruijnIndex::INNERMOST, i)))
87+
.map(|(k, v)| {
88+
let (kind, name) = k.into();
89+
(name, chalk_ir::WithKind::new(kind, v))
90+
})
91+
.collect()
92+
}
93+
94+
fn interner(&self) -> &ChalkIr {
95+
&ChalkIr
96+
}
8197
}
8298

8399
macro_rules! lower_param_map {
@@ -709,6 +725,9 @@ impl LowerWithEnv for Ty {
709725
TypeLookup::Opaque(id) => {
710726
(chalk_ir::TypeName::OpaqueType(id), env.opaque_kind(id))
711727
}
728+
TypeLookup::Generator(id) => {
729+
(chalk_ir::TypeName::Generator(id), env.generator_kind(id))
730+
}
712731

713732
TypeLookup::Foreign(_) | TypeLookup::Trait(_) => {
714733
panic!("Unexpected apply type")
@@ -1070,6 +1089,8 @@ pub fn lower_goal(goal: &Goal, program: &LoweredProgram) -> LowerResult<chalk_ir
10701089
closure_ids: &program.closure_ids,
10711090
trait_ids: &program.trait_ids,
10721091
opaque_ty_ids: &program.opaque_ty_ids,
1092+
generator_ids: &program.generator_ids,
1093+
generator_kinds: &program.generator_kinds,
10731094
adt_kinds: &program.adt_kinds,
10741095
fn_def_kinds: &program.fn_def_kinds,
10751096
closure_kinds: &program.closure_kinds,

chalk-integration/src/lowering/env.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use chalk_ir::interner::HasInterner;
22
use chalk_ir::{
3-
self, AdtId, BoundVar, ClosureId, DebruijnIndex, FnDefId, OpaqueTyId, TraitId, VariableKinds,
3+
self, AdtId, BoundVar, ClosureId, DebruijnIndex, FnDefId, GeneratorId, OpaqueTyId, TraitId,
4+
VariableKinds,
45
};
56
use chalk_ir::{cast::Cast, ForeignDefId, WithKind};
67
use chalk_parse::ast::*;
@@ -15,13 +16,15 @@ pub type AdtIds = BTreeMap<Ident, chalk_ir::AdtId<ChalkIr>>;
1516
pub type FnDefIds = BTreeMap<Ident, chalk_ir::FnDefId<ChalkIr>>;
1617
pub type ClosureIds = BTreeMap<Ident, chalk_ir::ClosureId<ChalkIr>>;
1718
pub type TraitIds = BTreeMap<Ident, chalk_ir::TraitId<ChalkIr>>;
19+
pub type GeneratorIds = BTreeMap<Ident, chalk_ir::GeneratorId<ChalkIr>>;
1820
pub type OpaqueTyIds = BTreeMap<Ident, chalk_ir::OpaqueTyId<ChalkIr>>;
1921
pub type AdtKinds = BTreeMap<chalk_ir::AdtId<ChalkIr>, TypeKind>;
2022
pub type FnDefKinds = BTreeMap<chalk_ir::FnDefId<ChalkIr>, TypeKind>;
2123
pub type ClosureKinds = BTreeMap<chalk_ir::ClosureId<ChalkIr>, TypeKind>;
2224
pub type TraitKinds = BTreeMap<chalk_ir::TraitId<ChalkIr>, TypeKind>;
2325
pub type AutoTraits = BTreeMap<chalk_ir::TraitId<ChalkIr>, bool>;
2426
pub type OpaqueTyKinds = BTreeMap<chalk_ir::OpaqueTyId<ChalkIr>, TypeKind>;
27+
pub type GeneratorKinds = BTreeMap<chalk_ir::GeneratorId<ChalkIr>, TypeKind>;
2528
pub type AssociatedTyLookups = BTreeMap<(chalk_ir::TraitId<ChalkIr>, Ident), AssociatedTyLookup>;
2629
pub type AssociatedTyValueIds =
2730
BTreeMap<(chalk_ir::ImplId<ChalkIr>, Ident), AssociatedTyValueId<ChalkIr>>;
@@ -46,6 +49,8 @@ pub struct Env<'k> {
4649
pub associated_ty_lookups: &'k AssociatedTyLookups,
4750
pub auto_traits: &'k AutoTraits,
4851
pub foreign_ty_ids: &'k ForeignIds,
52+
pub generator_ids: &'k GeneratorIds,
53+
pub generator_kinds: &'k GeneratorKinds,
4954
/// GenericArg identifiers are used as keys, therefore
5055
/// all identifiers in an environment must be unique (no shadowing).
5156
pub parameter_map: ParameterMap,
@@ -78,6 +83,7 @@ pub enum TypeLookup<'k> {
7883
Opaque(OpaqueTyId<ChalkIr>),
7984
Foreign(ForeignDefId<ChalkIr>),
8085
Trait(TraitId<ChalkIr>),
86+
Generator(GeneratorId<ChalkIr>),
8187
}
8288

8389
impl Env<'_> {
@@ -128,6 +134,9 @@ impl Env<'_> {
128134
Ok(TypeLookup::Closure(id)) => {
129135
apply(self.closure_kind(id), chalk_ir::TypeName::Closure(id))
130136
}
137+
Ok(TypeLookup::Generator(id)) => {
138+
apply(self.generator_kind(id), chalk_ir::TypeName::Generator(id))
139+
}
131140
Ok(TypeLookup::Opaque(id)) => Ok(chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(
132141
chalk_ir::OpaqueTy {
133142
opaque_ty_id: id,
@@ -162,6 +171,8 @@ impl Env<'_> {
162171
Ok(TypeLookup::Foreign(*id))
163172
} else if let Some(id) = self.trait_ids.get(&name.str) {
164173
Ok(TypeLookup::Trait(*id))
174+
} else if let Some(id) = self.generator_ids.get(&name.str) {
175+
Ok(TypeLookup::Generator(*id))
165176
} else {
166177
Err(RustIrError::NotStruct(name.clone()))
167178
}
@@ -203,6 +214,10 @@ impl Env<'_> {
203214
&self.opaque_ty_kinds[&id]
204215
}
205216

217+
pub fn generator_kind(&self, id: chalk_ir::GeneratorId<ChalkIr>) -> &TypeKind {
218+
&self.generator_kinds[&id]
219+
}
220+
206221
pub fn lookup_associated_ty(
207222
&self,
208223
trait_id: TraitId<ChalkIr>,

chalk-integration/src/lowering/program_lowerer.rs

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
use chalk_ir::cast::Cast;
22
use chalk_ir::{
3-
self, AdtId, AssocTypeId, BoundVar, ClosureId, DebruijnIndex, FnDefId, ForeignDefId, ImplId,
4-
OpaqueTyId, TraitId, TyKind, VariableKinds,
3+
self, AdtId, AssocTypeId, BoundVar, ClosureId, DebruijnIndex, FnDefId, ForeignDefId,
4+
GeneratorId, ImplId, OpaqueTyId, TraitId, TyKind, VariableKinds,
55
};
66
use chalk_parse::ast::*;
77
use chalk_solve::rust_ir::{
8-
self, Anonymize, AssociatedTyValueId, OpaqueTyDatum, OpaqueTyDatumBound,
8+
self, Anonymize, AssociatedTyValueId, GeneratorDatum, GeneratorInputOutputDatum,
9+
GeneratorWitnessDatum, GeneratorWitnessExistential, OpaqueTyDatum, OpaqueTyDatumBound,
910
};
1011
use rust_ir::IntoWhereClauses;
1112
use std::collections::{BTreeMap, HashSet};
@@ -32,6 +33,8 @@ pub(super) struct ProgramLowerer {
3233
opaque_ty_ids: OpaqueTyIds,
3334
adt_kinds: AdtKinds,
3435
fn_def_kinds: FnDefKinds,
36+
generator_ids: GeneratorIds,
37+
generator_kinds: GeneratorKinds,
3538
closure_kinds: ClosureKinds,
3639
trait_kinds: TraitKinds,
3740
opaque_ty_kinds: OpaqueTyKinds,
@@ -125,6 +128,11 @@ impl ProgramLowerer {
125128
self.foreign_ty_ids
126129
.insert(ident.str.clone(), ForeignDefId(raw_id));
127130
}
131+
Item::GeneratorDefn(defn) => {
132+
let id = GeneratorId(raw_id);
133+
self.generator_ids.insert(defn.name.str.clone(), id);
134+
self.generator_kinds.insert(id, defn.lower_type_kind()?);
135+
}
128136
Item::Impl(_) => continue,
129137
Item::Clause(_) => continue,
130138
};
@@ -145,6 +153,8 @@ impl ProgramLowerer {
145153
let mut associated_ty_data = BTreeMap::new();
146154
let mut associated_ty_values = BTreeMap::new();
147155
let mut opaque_ty_data = BTreeMap::new();
156+
let mut generator_data = BTreeMap::new();
157+
let mut generator_witness_data = BTreeMap::new();
148158
let mut hidden_opaque_types = BTreeMap::new();
149159
let mut custom_clauses = Vec::new();
150160

@@ -160,6 +170,8 @@ impl ProgramLowerer {
160170
trait_kinds: &self.trait_kinds,
161171
opaque_ty_ids: &self.opaque_ty_ids,
162172
opaque_ty_kinds: &self.opaque_ty_kinds,
173+
generator_ids: &self.generator_ids,
174+
generator_kinds: &self.generator_kinds,
163175
associated_ty_lookups: &self.associated_ty_lookups,
164176
parameter_map: BTreeMap::new(),
165177
auto_traits: &self.auto_traits,
@@ -356,6 +368,51 @@ impl ProgramLowerer {
356368
);
357369
}
358370
}
371+
Item::GeneratorDefn(ref defn) => {
372+
let variable_kinds = defn
373+
.variable_kinds
374+
.iter()
375+
.map(|k| k.lower())
376+
.collect::<Vec<_>>();
377+
378+
let witness_lifetimes = defn
379+
.witness_lifetimes
380+
.iter()
381+
.map(|i| VariableKind::Lifetime(i.clone()).lower())
382+
.collect::<Vec<_>>();
383+
384+
let input_output = empty_env.in_binders(variable_kinds.clone(), |env| {
385+
let yield_type = defn.yield_ty.lower(&env)?;
386+
let resume_type = defn.resume_ty.lower(&env)?;
387+
let return_type = defn.return_ty.lower(&env)?;
388+
let upvars: Result<Vec<_>, _> =
389+
defn.upvars.iter().map(|ty| ty.lower(&env)).collect();
390+
391+
Ok(GeneratorInputOutputDatum {
392+
resume_type,
393+
yield_type,
394+
return_type,
395+
upvars: upvars?,
396+
})
397+
})?;
398+
399+
let inner_types = empty_env.in_binders(variable_kinds, |env| {
400+
let witnesses = env.in_binders(witness_lifetimes, |env| {
401+
let witnesses: Result<Vec<_>, _> =
402+
defn.witness_types.iter().map(|ty| ty.lower(&env)).collect();
403+
witnesses
404+
})?;
405+
406+
Ok(GeneratorWitnessExistential { types: witnesses })
407+
})?;
408+
409+
let generator_datum = GeneratorDatum { input_output };
410+
let generator_witness = GeneratorWitnessDatum { inner_types };
411+
412+
let id = self.generator_ids[&defn.name.str];
413+
generator_data.insert(id, Arc::new(generator_datum));
414+
generator_witness_data.insert(id, Arc::new(generator_witness));
415+
}
359416
Item::Foreign(_) => {}
360417
}
361418
}
@@ -375,6 +432,10 @@ impl ProgramLowerer {
375432
fn_def_data,
376433
closure_inputs_and_output,
377434
closure_closure_kind,
435+
generator_ids: self.generator_ids,
436+
generator_kinds: self.generator_kinds,
437+
generator_data,
438+
generator_witness_data,
378439
trait_data,
379440
well_known_traits,
380441
impl_data,
@@ -416,6 +477,11 @@ lower_type_kind!(AdtDefn, Adt, |defn: &AdtDefn| defn.all_parameters());
416477
lower_type_kind!(FnDefn, FnDef, |defn: &FnDefn| defn.all_parameters());
417478
lower_type_kind!(ClosureDefn, Closure, |defn: &ClosureDefn| defn
418479
.all_parameters());
480+
lower_type_kind!(GeneratorDefn, Generator, |defn: &GeneratorDefn| defn
481+
.variable_kinds
482+
.iter()
483+
.map(|k| k.lower())
484+
.collect::<Vec<_>>());
419485
lower_type_kind!(TraitDefn, Trait, |defn: &TraitDefn| defn
420486
.variable_kinds
421487
.iter()

chalk-integration/src/program.rs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ use chalk_ir::could_match::CouldMatch;
44
use chalk_ir::debug::Angle;
55
use chalk_ir::{
66
debug::SeparatorTraitRef, AdtId, AliasTy, ApplicationTy, AssocTypeId, Binders,
7-
CanonicalVarKinds, ClosureId, FnDefId, ForeignDefId, GenericArg, Goal, Goals, ImplId, Lifetime,
8-
OpaqueTy, OpaqueTyId, ProgramClause, ProgramClauseImplication, ProgramClauses, ProjectionTy,
9-
Substitution, TraitId, Ty, TyData,
7+
CanonicalVarKinds, ClosureId, FnDefId, ForeignDefId, GeneratorId, GenericArg, Goal, Goals,
8+
ImplId, Lifetime, OpaqueTy, OpaqueTyId, ProgramClause, ProgramClauseImplication,
9+
ProgramClauses, ProjectionTy, Substitution, TraitId, Ty, TyData,
1010
};
1111
use chalk_solve::rust_ir::{
1212
AdtDatum, AdtRepr, AssociatedTyDatum, AssociatedTyValue, AssociatedTyValueId, ClosureKind,
13-
FnDefDatum, FnDefInputsAndOutputDatum, ImplDatum, ImplType, OpaqueTyDatum, TraitDatum,
14-
WellKnownTrait,
13+
FnDefDatum, FnDefInputsAndOutputDatum, GeneratorDatum, GeneratorWitnessDatum, ImplDatum,
14+
ImplType, OpaqueTyDatum, TraitDatum, WellKnownTrait,
1515
};
1616
use chalk_solve::split::Split;
1717
use chalk_solve::RustIrDatabase;
@@ -37,6 +37,15 @@ pub struct Program {
3737

3838
pub closure_kinds: BTreeMap<ClosureId<ChalkIr>, TypeKind>,
3939

40+
/// For each generator
41+
pub generator_ids: BTreeMap<Identifier, GeneratorId<ChalkIr>>,
42+
43+
pub generator_kinds: BTreeMap<GeneratorId<ChalkIr>, TypeKind>,
44+
45+
pub generator_data: BTreeMap<GeneratorId<ChalkIr>, Arc<GeneratorDatum<ChalkIr>>>,
46+
47+
pub generator_witness_data: BTreeMap<GeneratorId<ChalkIr>, Arc<GeneratorWitnessDatum<ChalkIr>>>,
48+
4049
/// From trait name to item-id. Used during lowering only.
4150
pub trait_ids: BTreeMap<Identifier, TraitId<ChalkIr>>,
4251

@@ -380,6 +389,17 @@ impl RustIrDatabase<ChalkIr> for Program {
380389
self.adt_data[&id].clone()
381390
}
382391

392+
fn generator_datum(&self, id: GeneratorId<ChalkIr>) -> Arc<GeneratorDatum<ChalkIr>> {
393+
self.generator_data[&id].clone()
394+
}
395+
396+
fn generator_witness_datum(
397+
&self,
398+
id: GeneratorId<ChalkIr>,
399+
) -> Arc<GeneratorWitnessDatum<ChalkIr>> {
400+
self.generator_witness_data[&id].clone()
401+
}
402+
383403
fn adt_repr(&self, id: AdtId<ChalkIr>) -> AdtRepr {
384404
self.adt_reprs[&id]
385405
}

chalk-ir/src/cast.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,15 @@ where
315315
}
316316
}
317317

318+
impl<I> CastTo<TypeName<I>> for GeneratorId<I>
319+
where
320+
I: Interner,
321+
{
322+
fn cast_to(self, _interner: &I) -> TypeName<I> {
323+
TypeName::Generator(self)
324+
}
325+
}
326+
318327
impl<I> CastTo<TypeName<I>> for FnDefId<I>
319328
where
320329
I: Interner,

chalk-ir/src/debug.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ impl<I: Interner> Debug for ClosureId<I> {
3535
}
3636
}
3737

38+
impl<I: Interner> Debug for GeneratorId<I> {
39+
fn fmt(&self, fmt: &mut Formatter<'_>) -> std::fmt::Result {
40+
I::debug_generator_id(*self, fmt)
41+
.unwrap_or_else(|| write!(fmt, "GeneratorId({:?})", self.0))
42+
}
43+
}
44+
3845
impl<I: Interner> Debug for ForeignDefId<I> {
3946
fn fmt(&self, fmt: &mut Formatter<'_>) -> std::fmt::Result {
4047
I::debug_foreign_def_id(*self, fmt)
@@ -205,6 +212,8 @@ impl<I: Interner> Debug for TypeName<I> {
205212
TypeName::Never => write!(fmt, "Never"),
206213
TypeName::Array => write!(fmt, "{{array}}"),
207214
TypeName::Closure(id) => write!(fmt, "{{closure:{:?}}}", id),
215+
TypeName::Generator(generator) => write!(fmt, "{:?}", generator),
216+
TypeName::GeneratorWitness(witness) => write!(fmt, "{:?}", witness),
208217
TypeName::Foreign(foreign_ty) => write!(fmt, "{:?}", foreign_ty),
209218
TypeName::Error => write!(fmt, "{{error}}"),
210219
}

chalk-ir/src/fold/boring_impls.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ id_fold!(AssocTypeId);
303303
id_fold!(OpaqueTyId);
304304
id_fold!(FnDefId);
305305
id_fold!(ClosureId);
306+
id_fold!(GeneratorId);
306307
id_fold!(ForeignDefId);
307308

308309
impl<I: Interner, TI: TargetInterner<I>> SuperFold<I, TI> for ProgramClauseData<I> {

0 commit comments

Comments
 (0)