Skip to content

Commit a27bfd0

Browse files
authored
Merge pull request #519 from jackh726/closure
Add closures
2 parents 5bf3a51 + 08efff0 commit a27bfd0

File tree

23 files changed

+872
-73
lines changed

23 files changed

+872
-73
lines changed

chalk-integration/src/db.rs

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ use crate::{
77
tls,
88
};
99
use chalk_ir::{
10-
AdtId, AssocTypeId, Canonical, ConstrainedSubst, Environment, FnDefId, GenericArg, Goal,
11-
ImplId, InEnvironment, OpaqueTyId, ProgramClause, ProgramClauses, TraitId, Ty, UCanonical,
10+
AdtId, AssocTypeId, Binders, Canonical, ClosureId, ConstrainedSubst, Environment, FnDefId,
11+
GenericArg, Goal, ImplId, InEnvironment, OpaqueTyId, ProgramClause, ProgramClauses,
12+
Substitution, TraitId, Ty, UCanonical,
1213
};
1314
use chalk_solve::rust_ir::{
14-
AdtDatum, AssociatedTyDatum, AssociatedTyValue, AssociatedTyValueId, FnDefDatum, ImplDatum,
15-
OpaqueTyDatum, TraitDatum, WellKnownTrait,
15+
AdtDatum, AssociatedTyDatum, AssociatedTyValue, AssociatedTyValueId, ClosureKind, FnDefDatum,
16+
FnDefInputsAndOutputDatum, ImplDatum, OpaqueTyDatum, TraitDatum, WellKnownTrait,
1617
};
1718
use chalk_solve::{RustIrDatabase, Solution, SolverChoice, SubstitutionResult};
1819
use salsa::Database;
@@ -154,4 +155,42 @@ impl RustIrDatabase<ChalkIr> for ChalkDatabase {
154155
fn is_object_safe(&self, trait_id: TraitId<ChalkIr>) -> bool {
155156
self.program_ir().unwrap().is_object_safe(trait_id)
156157
}
158+
159+
fn closure_inputs_and_output(
160+
&self,
161+
closure_id: ClosureId<ChalkIr>,
162+
substs: &Substitution<ChalkIr>,
163+
) -> Binders<FnDefInputsAndOutputDatum<ChalkIr>> {
164+
self.program_ir()
165+
.unwrap()
166+
.closure_inputs_and_output(closure_id, substs)
167+
}
168+
169+
fn closure_kind(
170+
&self,
171+
closure_id: ClosureId<ChalkIr>,
172+
substs: &Substitution<ChalkIr>,
173+
) -> ClosureKind {
174+
self.program_ir().unwrap().closure_kind(closure_id, substs)
175+
}
176+
177+
fn closure_upvars(
178+
&self,
179+
closure_id: ClosureId<ChalkIr>,
180+
substs: &Substitution<ChalkIr>,
181+
) -> Binders<Ty<ChalkIr>> {
182+
self.program_ir()
183+
.unwrap()
184+
.closure_upvars(closure_id, substs)
185+
}
186+
187+
fn closure_fn_substitution(
188+
&self,
189+
closure_id: ClosureId<ChalkIr>,
190+
substs: &Substitution<ChalkIr>,
191+
) -> Substitution<ChalkIr> {
192+
self.program_ir()
193+
.unwrap()
194+
.closure_fn_substitution(closure_id, substs)
195+
}
157196
}

chalk-integration/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub use interner::{Identifier, RawId};
2020
pub enum TypeSort {
2121
Struct,
2222
FnDef,
23+
Closure,
2324
Trait,
2425
Opaque,
2526
}

chalk-integration/src/lowering.rs

Lines changed: 152 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use crate::interner::{ChalkFnAbi, ChalkIr};
22
use chalk_ir::cast::{Cast, Caster};
33
use chalk_ir::interner::{HasInterner, Interner};
44
use chalk_ir::{
5-
self, AdtId, AssocTypeId, BoundVar, ClausePriority, DebruijnIndex, FnDefId, ImplId, OpaqueTyId,
6-
QuantifiedWhereClauses, Substitution, ToGenericArg, TraitId, TyKind,
5+
self, AdtId, AssocTypeId, BoundVar, ClausePriority, ClosureId, DebruijnIndex, FnDefId, ImplId,
6+
OpaqueTyId, QuantifiedWhereClauses, Substitution, ToGenericArg, TraitId, TyKind,
77
};
88
use chalk_parse::ast::*;
99
use chalk_solve::rust_ir::{
@@ -20,11 +20,13 @@ use crate::{Identifier as Ident, RawId, TypeKind, TypeSort};
2020

2121
type AdtIds = BTreeMap<Ident, chalk_ir::AdtId<ChalkIr>>;
2222
type FnDefIds = BTreeMap<Ident, chalk_ir::FnDefId<ChalkIr>>;
23+
type ClosureIds = BTreeMap<Ident, chalk_ir::ClosureId<ChalkIr>>;
2324
type TraitIds = BTreeMap<Ident, chalk_ir::TraitId<ChalkIr>>;
2425
type OpaqueTyIds = BTreeMap<Ident, chalk_ir::OpaqueTyId<ChalkIr>>;
2526
type AdtKinds = BTreeMap<chalk_ir::AdtId<ChalkIr>, TypeKind>;
2627
type FnDefKinds = BTreeMap<chalk_ir::FnDefId<ChalkIr>, TypeKind>;
2728
type FnDefAbis = BTreeMap<FnDefId<ChalkIr>, <ChalkIr as Interner>::FnAbi>;
29+
type ClosureKinds = BTreeMap<chalk_ir::ClosureId<ChalkIr>, TypeKind>;
2830
type TraitKinds = BTreeMap<chalk_ir::TraitId<ChalkIr>, TypeKind>;
2931
type OpaqueTyKinds = BTreeMap<chalk_ir::OpaqueTyId<ChalkIr>, TypeKind>;
3032
type AssociatedTyLookups = BTreeMap<(chalk_ir::TraitId<ChalkIr>, Ident), AssociatedTyLookup>;
@@ -42,6 +44,8 @@ struct Env<'k> {
4244
fn_def_ids: &'k FnDefIds,
4345
fn_def_kinds: &'k FnDefKinds,
4446
fn_def_abis: &'k FnDefAbis,
47+
closure_ids: &'k ClosureIds,
48+
closure_kinds: &'k ClosureKinds,
4549
trait_ids: &'k TraitIds,
4650
trait_kinds: &'k TraitKinds,
4751
opaque_ty_ids: &'k OpaqueTyIds,
@@ -80,6 +84,7 @@ struct AssociatedTyLookup {
8084
enum ApplyTypeLookup {
8185
Adt(AdtId<ChalkIr>),
8286
FnDef(FnDefId<ChalkIr>),
87+
Closure(ClosureId<ChalkIr>),
8388
Opaque(OpaqueTyId<ChalkIr>),
8489
}
8590

@@ -132,8 +137,27 @@ impl<'k> Env<'k> {
132137
actual: 0,
133138
});
134139
} else {
135-
return Ok(chalk_ir::TyData::Function(chalk_ir::Fn {
136-
num_binders: k.binders.len(interner),
140+
return Ok(chalk_ir::TyData::Apply(chalk_ir::ApplicationTy {
141+
name: chalk_ir::TypeName::FnDef(id.clone()),
142+
substitution: chalk_ir::Substitution::empty(interner),
143+
})
144+
.intern(interner)
145+
.cast(interner));
146+
}
147+
}
148+
149+
if let Some(id) = self.closure_ids.get(&name.str) {
150+
let k = self.closure_kind(*id);
151+
if k.binders.len(interner) > 0 {
152+
return Err(RustIrError::IncorrectNumberOfTypeParameters {
153+
identifier: name.clone(),
154+
expected: k.binders.len(interner),
155+
actual: 0,
156+
});
157+
} else {
158+
return Ok(chalk_ir::TyData::Apply(chalk_ir::ApplicationTy {
159+
name: chalk_ir::TypeName::Closure(id.clone()),
160+
// See note in `program`. Unlike rustc, we store upvars separately.
137161
substitution: chalk_ir::Substitution::empty(interner),
138162
})
139163
.intern(interner)
@@ -171,6 +195,10 @@ impl<'k> Env<'k> {
171195
return Ok(ApplyTypeLookup::FnDef(*id));
172196
}
173197

198+
if let Some(id) = self.closure_ids.get(&name.str) {
199+
return Ok(ApplyTypeLookup::Closure(*id));
200+
}
201+
174202
if let Some(id) = self.opaque_ty_ids.get(&name.str) {
175203
return Ok(ApplyTypeLookup::Opaque(*id));
176204
}
@@ -206,6 +234,10 @@ impl<'k> Env<'k> {
206234
&self.fn_def_kinds[&id]
207235
}
208236

237+
fn closure_kind(&self, id: chalk_ir::ClosureId<ChalkIr>) -> &TypeKind {
238+
&self.closure_kinds[&id]
239+
}
240+
209241
fn opaque_kind(&self, id: chalk_ir::OpaqueTyId<ChalkIr>) -> &TypeKind {
210242
&self.opaque_ty_kinds[&id]
211243
}
@@ -318,11 +350,13 @@ impl LowerProgram for Program {
318350

319351
let mut adt_ids = BTreeMap::new();
320352
let mut fn_def_ids = BTreeMap::new();
353+
let mut closure_ids = BTreeMap::new();
321354
let mut trait_ids = BTreeMap::new();
322355
let mut opaque_ty_ids = BTreeMap::new();
323356
let mut adt_kinds = BTreeMap::new();
324357
let mut fn_def_kinds = BTreeMap::new();
325358
let mut fn_def_abis = BTreeMap::new();
359+
let mut closure_kinds = BTreeMap::new();
326360
let mut trait_kinds = BTreeMap::new();
327361
let mut opaque_ty_kinds = BTreeMap::new();
328362
let mut object_safe_traits = HashSet::new();
@@ -341,6 +375,12 @@ impl LowerProgram for Program {
341375
fn_def_kinds.insert(id, type_kind);
342376
fn_def_abis.insert(id, defn.abi.lower()?);
343377
}
378+
Item::ClosureDefn(defn) => {
379+
let type_kind = defn.lower_type_kind()?;
380+
let id = ClosureId(raw_id);
381+
closure_ids.insert(defn.name.str.clone(), id);
382+
closure_kinds.insert(id, type_kind);
383+
}
344384
Item::TraitDefn(defn) => {
345385
let type_kind = defn.lower_type_kind()?;
346386
let id = TraitId(raw_id);
@@ -364,6 +404,9 @@ impl LowerProgram for Program {
364404

365405
let mut adt_data = BTreeMap::new();
366406
let mut fn_def_data = BTreeMap::new();
407+
let mut closure_inputs_and_output = BTreeMap::new();
408+
let mut closure_closure_kind = BTreeMap::new();
409+
let mut closure_upvars = BTreeMap::new();
367410
let mut trait_data = BTreeMap::new();
368411
let mut well_known_traits = BTreeMap::new();
369412
let mut impl_data = BTreeMap::new();
@@ -379,6 +422,8 @@ impl LowerProgram for Program {
379422
fn_def_ids: &fn_def_ids,
380423
fn_def_kinds: &fn_def_kinds,
381424
fn_def_abis: &fn_def_abis,
425+
closure_ids: &closure_ids,
426+
closure_kinds: &closure_kinds,
382427
trait_ids: &trait_ids,
383428
trait_kinds: &trait_kinds,
384429
opaque_ty_ids: &opaque_ty_ids,
@@ -399,6 +444,26 @@ impl LowerProgram for Program {
399444
Arc::new(defn.lower_fn_def(fn_def_id, &empty_env)?),
400445
);
401446
}
447+
Item::ClosureDefn(ref defn) => {
448+
let closure_def_id = ClosureId(raw_id);
449+
let (kind, inputs_and_output) = defn.lower_closure(&empty_env)?;
450+
closure_closure_kind.insert(closure_def_id, kind);
451+
closure_inputs_and_output.insert(closure_def_id, inputs_and_output);
452+
let upvars = empty_env.in_binders(defn.all_parameters(), |env| {
453+
let upvar_tys: LowerResult<Vec<chalk_ir::Ty<ChalkIr>>> =
454+
defn.upvars.iter().map(|ty| ty.lower(&env)).collect();
455+
let substitution = chalk_ir::Substitution::from(
456+
&ChalkIr,
457+
upvar_tys?.into_iter().map(|ty| ty.cast(&ChalkIr)),
458+
);
459+
Ok(chalk_ir::TyData::Apply(chalk_ir::ApplicationTy {
460+
name: chalk_ir::TypeName::Tuple(defn.upvars.len()),
461+
substitution,
462+
})
463+
.intern(&ChalkIr))
464+
})?;
465+
closure_upvars.insert(closure_def_id, upvars);
466+
}
402467
Item::TraitDefn(ref trait_defn) => {
403468
let trait_id = TraitId(raw_id);
404469
let trait_datum = trait_defn.lower_trait(trait_id, &empty_env)?;
@@ -556,12 +621,17 @@ impl LowerProgram for Program {
556621
let program = LoweredProgram {
557622
adt_ids,
558623
fn_def_ids,
624+
closure_ids,
625+
closure_upvars,
626+
closure_kinds,
559627
trait_ids,
560628
adt_kinds,
561629
fn_def_kinds,
562630
trait_kinds,
563631
adt_data,
564632
fn_def_data,
633+
closure_inputs_and_output,
634+
closure_closure_kind,
565635
trait_data,
566636
well_known_traits,
567637
impl_data,
@@ -657,6 +727,16 @@ impl LowerParameterMap for FnDefn {
657727
}
658728
}
659729

730+
impl LowerParameterMap for ClosureDefn {
731+
fn synthetic_parameters(&self) -> Option<chalk_ir::WithKind<ChalkIr, Ident>> {
732+
None
733+
}
734+
735+
fn declared_parameters(&self) -> &[VariableKind] {
736+
&self.variable_kinds
737+
}
738+
}
739+
660740
impl LowerParameterMap for Impl {
661741
fn synthetic_parameters(&self) -> Option<chalk_ir::WithKind<ChalkIr, Ident>> {
662742
None
@@ -794,6 +874,20 @@ impl LowerWhereClauses for FnDefn {
794874
}
795875
}
796876

877+
impl LowerTypeKind for ClosureDefn {
878+
fn lower_type_kind(&self) -> LowerResult<TypeKind> {
879+
let interner = &ChalkIr;
880+
Ok(TypeKind {
881+
sort: TypeSort::Closure,
882+
name: self.name.str.clone(),
883+
binders: chalk_ir::Binders::new(
884+
chalk_ir::VariableKinds::from(interner, self.all_parameters().anonymize()),
885+
crate::Unit,
886+
),
887+
})
888+
}
889+
}
890+
797891
impl LowerWhereClauses for StructDefn {
798892
fn where_clauses(&self) -> &[QuantifiedWhereClause] {
799893
&self.where_clauses
@@ -1032,11 +1126,12 @@ impl LowerFnDefn for FnDefn {
10321126
env: &Env,
10331127
) -> LowerResult<rust_ir::FnDefDatum<ChalkIr>> {
10341128
let binders = env.in_binders(self.all_parameters(), |env| {
1035-
let args: LowerResult<_> = self.argument_types.iter().map(|t| t.lower(env)).collect();
10361129
let where_clauses = self.lower_where_clauses(env)?;
1037-
let return_type = self.return_type.lower(env)?;
10381130

1039-
let inputs_and_output = env.in_binders(vec![], |_| {
1131+
let inputs_and_output = env.in_binders(vec![], |env| {
1132+
let args: LowerResult<_> =
1133+
self.argument_types.iter().map(|t| t.lower(env)).collect();
1134+
let return_type = self.return_type.lower(env)?;
10401135
Ok(rust_ir::FnDefInputsAndOutputDatum {
10411136
argument_types: args?,
10421137
return_type,
@@ -1070,6 +1165,51 @@ impl LowerFnAbi for FnAbi {
10701165
}
10711166
}
10721167

1168+
trait LowerClosureDefn {
1169+
fn lower_closure(
1170+
&self,
1171+
env: &Env,
1172+
) -> LowerResult<(
1173+
rust_ir::ClosureKind,
1174+
chalk_ir::Binders<rust_ir::FnDefInputsAndOutputDatum<ChalkIr>>,
1175+
)>;
1176+
}
1177+
1178+
impl LowerClosureDefn for ClosureDefn {
1179+
fn lower_closure(
1180+
&self,
1181+
env: &Env,
1182+
) -> LowerResult<(
1183+
rust_ir::ClosureKind,
1184+
chalk_ir::Binders<rust_ir::FnDefInputsAndOutputDatum<ChalkIr>>,
1185+
)> {
1186+
let inputs_and_output = env.in_binders(self.all_parameters(), |env| {
1187+
let args: LowerResult<_> = self.argument_types.iter().map(|t| t.lower(env)).collect();
1188+
let return_type = self.return_type.lower(env)?;
1189+
Ok(rust_ir::FnDefInputsAndOutputDatum {
1190+
argument_types: args?,
1191+
return_type,
1192+
})
1193+
})?;
1194+
1195+
Ok((self.kind.lower_closure_kind()?, inputs_and_output))
1196+
}
1197+
}
1198+
1199+
trait LowerClosureKind {
1200+
fn lower_closure_kind(&self) -> LowerResult<rust_ir::ClosureKind>;
1201+
}
1202+
1203+
impl LowerClosureKind for ClosureKind {
1204+
fn lower_closure_kind(&self) -> LowerResult<rust_ir::ClosureKind> {
1205+
Ok(match self {
1206+
ClosureKind::Fn => rust_ir::ClosureKind::Fn,
1207+
ClosureKind::FnMut => rust_ir::ClosureKind::FnMut,
1208+
ClosureKind::FnOnce => rust_ir::ClosureKind::FnOnce,
1209+
})
1210+
}
1211+
}
1212+
10731213
trait LowerTraitRef {
10741214
fn lower(&self, env: &Env) -> LowerResult<chalk_ir::TraitRef<ChalkIr>>;
10751215
}
@@ -1369,6 +1509,9 @@ impl LowerTy for Ty {
13691509
ApplyTypeLookup::FnDef(id) => {
13701510
(chalk_ir::TypeName::FnDef(id), env.fn_def_kind(id))
13711511
}
1512+
ApplyTypeLookup::Closure(id) => {
1513+
(chalk_ir::TypeName::Closure(id), env.closure_kind(id))
1514+
}
13721515
ApplyTypeLookup::Opaque(id) => {
13731516
(chalk_ir::TypeName::OpaqueType(id), env.opaque_kind(id))
13741517
}
@@ -1761,11 +1904,13 @@ impl LowerGoal<LoweredProgram> for Goal {
17611904
let env = Env {
17621905
adt_ids: &program.adt_ids,
17631906
fn_def_ids: &program.fn_def_ids,
1907+
closure_ids: &program.closure_ids,
17641908
trait_ids: &program.trait_ids,
17651909
opaque_ty_ids: &program.opaque_ty_ids,
17661910
adt_kinds: &program.adt_kinds,
17671911
fn_def_kinds: &program.fn_def_kinds,
17681912
fn_def_abis: &fn_def_abis,
1913+
closure_kinds: &program.closure_kinds,
17691914
trait_kinds: &program.trait_kinds,
17701915
opaque_ty_kinds: &program.opaque_ty_kinds,
17711916
associated_ty_lookups: &associated_ty_lookups,

0 commit comments

Comments
 (0)