Skip to content

Commit a4072ff

Browse files
committed
More closures work
1 parent 35f5967 commit a4072ff

File tree

12 files changed

+257
-95
lines changed

12 files changed

+257
-95
lines changed

chalk-integration/src/db.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ use crate::{
77
tls,
88
};
99
use chalk_ir::{
10-
AdtId, AssocTypeId, Canonical, ClosureId, ConstrainedSubst, Environment, FnDefId, GenericArg,
11-
Goal, ImplId, InEnvironment, OpaqueTyId, ProgramClause, ProgramClauses, Substitution, TraitId,
12-
Ty, UCanonical,
10+
AdtId, AssocTypeId, Binders, Canonical, ClosureId, ConstrainedSubst, Environment, FnDefId,
11+
GenericArg, Goal, ImplId, InEnvironment, OpaqueTyId, ProgramClause, ProgramClauses,
12+
Substitution, TraitId, Ty, UCanonical,
1313
};
1414
use chalk_solve::rust_ir::{
1515
AdtDatum, AssociatedTyDatum, AssociatedTyValue, AssociatedTyValueId, ClosureDatum, FnDefDatum,
@@ -168,7 +168,7 @@ impl RustIrDatabase<ChalkIr> for ChalkDatabase {
168168
&self,
169169
closure_id: ClosureId<ChalkIr>,
170170
substs: &Substitution<ChalkIr>,
171-
) -> Ty<ChalkIr> {
171+
) -> Binders<Ty<ChalkIr>> {
172172
self.program_ir()
173173
.unwrap()
174174
.closure_upvars(closure_id, substs)

chalk-integration/src/lib.rs

+1
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

+63-13
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type OpaqueTyIds = BTreeMap<Ident, chalk_ir::OpaqueTyId<ChalkIr>>;
2626
type AdtKinds = BTreeMap<chalk_ir::AdtId<ChalkIr>, TypeKind>;
2727
type FnDefKinds = BTreeMap<chalk_ir::FnDefId<ChalkIr>, TypeKind>;
2828
type FnDefAbis = BTreeMap<FnDefId<ChalkIr>, <ChalkIr as Interner>::FnAbi>;
29+
type ClosureKinds = BTreeMap<chalk_ir::ClosureId<ChalkIr>, TypeKind>;
2930
type TraitKinds = BTreeMap<chalk_ir::TraitId<ChalkIr>, TypeKind>;
3031
type OpaqueTyKinds = BTreeMap<chalk_ir::OpaqueTyId<ChalkIr>, TypeKind>;
3132
type AssociatedTyLookups = BTreeMap<(chalk_ir::TraitId<ChalkIr>, Ident), AssociatedTyLookup>;
@@ -44,6 +45,7 @@ struct Env<'k> {
4445
fn_def_kinds: &'k FnDefKinds,
4546
fn_def_abis: &'k FnDefAbis,
4647
closure_ids: &'k ClosureIds,
48+
closure_kinds: &'k ClosureKinds,
4749
trait_ids: &'k TraitIds,
4850
trait_kinds: &'k TraitKinds,
4951
opaque_ty_ids: &'k OpaqueTyIds,
@@ -82,6 +84,7 @@ struct AssociatedTyLookup {
8284
enum ApplyTypeLookup {
8385
Adt(AdtId<ChalkIr>),
8486
FnDef(FnDefId<ChalkIr>),
87+
Closure(ClosureId<ChalkIr>),
8588
Opaque(OpaqueTyId<ChalkIr>),
8689
}
8790

@@ -146,18 +149,8 @@ impl<'k> Env<'k> {
146149
if let Some(id) = self.closure_ids.get(&name.str) {
147150
return Ok(chalk_ir::TyData::Apply(chalk_ir::ApplicationTy {
148151
name: chalk_ir::TypeName::Closure(id.clone()),
149-
// XXX closure upvars
150-
substitution: chalk_ir::Substitution::from(
151-
interner,
152-
Some(
153-
chalk_ir::TyData::Apply(chalk_ir::ApplicationTy {
154-
name: chalk_ir::TypeName::Tuple(0),
155-
substitution: chalk_ir::Substitution::empty(interner),
156-
})
157-
.intern(interner)
158-
.cast(interner),
159-
),
160-
),
152+
// See note in `program`. Unlike rustc, we store upvars separately.
153+
substitution: chalk_ir::Substitution::empty(interner),
161154
})
162155
.intern(interner)
163156
.cast(interner));
@@ -193,6 +186,10 @@ impl<'k> Env<'k> {
193186
return Ok(ApplyTypeLookup::FnDef(*id));
194187
}
195188

189+
if let Some(id) = self.closure_ids.get(&name.str) {
190+
return Ok(ApplyTypeLookup::Closure(*id));
191+
}
192+
196193
if let Some(id) = self.opaque_ty_ids.get(&name.str) {
197194
return Ok(ApplyTypeLookup::Opaque(*id));
198195
}
@@ -228,6 +225,10 @@ impl<'k> Env<'k> {
228225
&self.fn_def_kinds[&id]
229226
}
230227

228+
fn closure_kind(&self, id: chalk_ir::ClosureId<ChalkIr>) -> &TypeKind {
229+
&self.closure_kinds[&id]
230+
}
231+
231232
fn opaque_kind(&self, id: chalk_ir::OpaqueTyId<ChalkIr>) -> &TypeKind {
232233
&self.opaque_ty_kinds[&id]
233234
}
@@ -346,6 +347,7 @@ impl LowerProgram for Program {
346347
let mut adt_kinds = BTreeMap::new();
347348
let mut fn_def_kinds = BTreeMap::new();
348349
let mut fn_def_abis = BTreeMap::new();
350+
let mut closure_kinds = BTreeMap::new();
349351
let mut trait_kinds = BTreeMap::new();
350352
let mut opaque_ty_kinds = BTreeMap::new();
351353
let mut object_safe_traits = HashSet::new();
@@ -365,8 +367,10 @@ impl LowerProgram for Program {
365367
fn_def_abis.insert(id, defn.abi.lower()?);
366368
}
367369
Item::ClosureDefn(defn) => {
370+
let type_kind = defn.lower_type_kind()?;
368371
let id = ClosureId(raw_id);
369372
closure_ids.insert(defn.name.str.clone(), id);
373+
closure_kinds.insert(id, type_kind);
370374
}
371375
Item::TraitDefn(defn) => {
372376
let type_kind = defn.lower_type_kind()?;
@@ -392,6 +396,7 @@ impl LowerProgram for Program {
392396
let mut adt_data = BTreeMap::new();
393397
let mut fn_def_data = BTreeMap::new();
394398
let mut closure_data = BTreeMap::new();
399+
let mut closure_upvars = BTreeMap::new();
395400
let mut trait_data = BTreeMap::new();
396401
let mut well_known_traits = BTreeMap::new();
397402
let mut impl_data = BTreeMap::new();
@@ -408,6 +413,7 @@ impl LowerProgram for Program {
408413
fn_def_kinds: &fn_def_kinds,
409414
fn_def_abis: &fn_def_abis,
410415
closure_ids: &closure_ids,
416+
closure_kinds: &closure_kinds,
411417
trait_ids: &trait_ids,
412418
trait_kinds: &trait_kinds,
413419
opaque_ty_ids: &opaque_ty_ids,
@@ -434,6 +440,20 @@ impl LowerProgram for Program {
434440
closure_def_id,
435441
Arc::new(defn.lower_closure(closure_def_id, &empty_env)?),
436442
);
443+
let upvars = empty_env.in_binders(defn.all_parameters(), |env| {
444+
let upvar_tys: LowerResult<Vec<chalk_ir::Ty<ChalkIr>>> =
445+
defn.upvars.iter().map(|ty| ty.lower(&env)).collect();
446+
let substitution = chalk_ir::Substitution::from(
447+
&ChalkIr,
448+
upvar_tys?.into_iter().map(|ty| ty.cast(&ChalkIr)),
449+
);
450+
Ok(chalk_ir::TyData::Apply(chalk_ir::ApplicationTy {
451+
name: chalk_ir::TypeName::Tuple(defn.upvars.len()),
452+
substitution,
453+
})
454+
.intern(&ChalkIr))
455+
})?;
456+
closure_upvars.insert(closure_def_id, upvars);
437457
}
438458
Item::TraitDefn(ref trait_defn) => {
439459
let trait_id = TraitId(raw_id);
@@ -593,6 +613,8 @@ impl LowerProgram for Program {
593613
adt_ids,
594614
fn_def_ids,
595615
closure_ids,
616+
closure_upvars,
617+
closure_kinds,
596618
trait_ids,
597619
adt_kinds,
598620
fn_def_kinds,
@@ -695,6 +717,16 @@ impl LowerParameterMap for FnDefn {
695717
}
696718
}
697719

720+
impl LowerParameterMap for ClosureDefn {
721+
fn synthetic_parameters(&self) -> Option<chalk_ir::WithKind<ChalkIr, Ident>> {
722+
None
723+
}
724+
725+
fn declared_parameters(&self) -> &[VariableKind] {
726+
&self.variable_kinds
727+
}
728+
}
729+
698730
impl LowerParameterMap for Impl {
699731
fn synthetic_parameters(&self) -> Option<chalk_ir::WithKind<ChalkIr, Ident>> {
700732
None
@@ -832,6 +864,20 @@ impl LowerWhereClauses for FnDefn {
832864
}
833865
}
834866

867+
impl LowerTypeKind for ClosureDefn {
868+
fn lower_type_kind(&self) -> LowerResult<TypeKind> {
869+
let interner = &ChalkIr;
870+
Ok(TypeKind {
871+
sort: TypeSort::Closure,
872+
name: self.name.str.clone(),
873+
binders: chalk_ir::Binders::new(
874+
chalk_ir::VariableKinds::from(interner, self.all_parameters().anonymize()),
875+
crate::Unit,
876+
),
877+
})
878+
}
879+
}
880+
835881
impl LowerWhereClauses for StructDefn {
836882
fn where_clauses(&self) -> &[QuantifiedWhereClause] {
837883
&self.where_clauses
@@ -1123,7 +1169,7 @@ impl LowerClosureDefn for ClosureDefn {
11231169
closure_id: chalk_ir::ClosureId<ChalkIr>,
11241170
env: &Env,
11251171
) -> LowerResult<rust_ir::ClosureDatum<ChalkIr>> {
1126-
let inputs_and_output = env.in_binders(vec![], |env| {
1172+
let inputs_and_output = env.in_binders(self.all_parameters(), |env| {
11271173
let args: LowerResult<_> = self.argument_types.iter().map(|t| t.lower(env)).collect();
11281174
let return_type = self.return_type.lower(env)?;
11291175
Ok(rust_ir::FnDefInputsAndOutputDatum {
@@ -1453,6 +1499,9 @@ impl LowerTy for Ty {
14531499
ApplyTypeLookup::FnDef(id) => {
14541500
(chalk_ir::TypeName::FnDef(id), env.fn_def_kind(id))
14551501
}
1502+
ApplyTypeLookup::Closure(id) => {
1503+
(chalk_ir::TypeName::Closure(id), env.closure_kind(id))
1504+
}
14561505
ApplyTypeLookup::Opaque(id) => {
14571506
(chalk_ir::TypeName::OpaqueType(id), env.opaque_kind(id))
14581507
}
@@ -1852,6 +1901,7 @@ impl LowerGoal<LoweredProgram> for Goal {
18521901
adt_kinds: &program.adt_kinds,
18531902
fn_def_kinds: &program.fn_def_kinds,
18541903
fn_def_abis: &fn_def_abis,
1904+
closure_kinds: &program.closure_kinds,
18551905
trait_kinds: &program.trait_kinds,
18561906
opaque_ty_kinds: &program.opaque_ty_kinds,
18571907
associated_ty_lookups: &associated_ty_lookups,

chalk-integration/src/program.rs

+14-11
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use crate::{tls, Identifier, TypeKind};
33
use chalk_ir::could_match::CouldMatch;
44
use chalk_ir::debug::Angle;
55
use chalk_ir::{
6-
debug::SeparatorTraitRef, AdtId, AliasTy, ApplicationTy, AssocTypeId, ClosureId, FnDefId,
7-
GenericArg, Goal, Goals, ImplId, Lifetime, OpaqueTy, OpaqueTyId, ProgramClause,
6+
debug::SeparatorTraitRef, AdtId, AliasTy, ApplicationTy, AssocTypeId, Binders, ClosureId,
7+
FnDefId, GenericArg, Goal, Goals, ImplId, Lifetime, OpaqueTy, OpaqueTyId, ProgramClause,
88
ProgramClauseImplication, ProgramClauses, ProjectionTy, Substitution, TraitId, Ty,
99
};
1010
use chalk_solve::rust_ir::{
@@ -31,6 +31,10 @@ pub struct Program {
3131

3232
pub closure_ids: BTreeMap<Identifier, ClosureId<ChalkIr>>,
3333

34+
pub closure_upvars: BTreeMap<ClosureId<ChalkIr>, Binders<Ty<ChalkIr>>>,
35+
36+
pub closure_kinds: BTreeMap<ClosureId<ChalkIr>, TypeKind>,
37+
3438
/// From trait name to item-id. Used during lowering only.
3539
pub trait_ids: BTreeMap<Identifier, TraitId<ChalkIr>>,
3640

@@ -420,21 +424,20 @@ impl RustIrDatabase<ChalkIr> for Program {
420424
fn closure_datum(
421425
&self,
422426
closure_id: ClosureId<ChalkIr>,
423-
substs: &Substitution<ChalkIr>,
427+
_substs: &Substitution<ChalkIr>,
424428
) -> Arc<ClosureDatum<ChalkIr>> {
425429
self.closure_data[&closure_id].clone()
426430
}
427431

428432
fn closure_upvars(
429433
&self,
430434
closure_id: ClosureId<ChalkIr>,
431-
substs: &Substitution<ChalkIr>,
432-
) -> Ty<ChalkIr> {
433-
substs
434-
.parameters(self.interner())
435-
.last()
436-
.unwrap()
437-
.assert_ty_ref(self.interner())
438-
.clone()
435+
_substs: &Substitution<ChalkIr>,
436+
) -> Binders<Ty<ChalkIr>> {
437+
// This is different to how rustc does it. In rustc,
438+
// upvars are stored in the last substitution parameter.
439+
// It's just easier this way, and from `chalk-solve`s POV,
440+
// this is opaque anyways.
441+
self.closure_upvars[&closure_id].clone()
439442
}
440443
}

chalk-parse/src/ast.rs

+2
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,10 @@ pub struct FnDefn {
5959
pub struct ClosureDefn {
6060
pub name: Identifier,
6161
pub kind: ClosureKind,
62+
pub variable_kinds: Vec<VariableKind>,
6263
pub argument_types: Vec<Ty>,
6364
pub return_type: Ty,
65+
pub upvars: Vec<Ty>,
6466
}
6567

6668
#[derive(Clone, Eq, PartialEq, Debug)]

chalk-parse/src/parser.lalrpop

+12-5
Original file line numberDiff line numberDiff line change
@@ -104,18 +104,25 @@ FnArgs: Vec<Ty> = {
104104
};
105105

106106
ClosureDefn: ClosureDefn = {
107-
"closure" <n:Id> "(" <s:ClosureSelf> ")" ";" => ClosureDefn {
107+
"closure" <n:Id> <p:Angle<VariableKind>> "(" <s:ClosureSelf> <args:ClosureArgs> ")" <ret_ty:FnReturn?>
108+
"{" <upvars:SemiColon<Ty>> "}" => ClosureDefn {
108109
name: n,
109110
kind: s,
110-
argument_types: vec![],
111-
return_type: Ty::Tuple { types: Vec::new() },
111+
variable_kinds: p,
112+
argument_types: args,
113+
return_type: ret_ty.unwrap_or_else(|| Ty::Tuple { types: Vec::new() }),
114+
upvars: upvars,
112115
}
113116
}
114117

115118
ClosureSelf: ClosureKind = {
116119
"self" => ClosureKind::FnOnce,
117-
"mutself" => ClosureKind::FnMut,
118-
"refself" => ClosureKind::Fn,
120+
"&" "mut" "self" => ClosureKind::FnMut,
121+
"&" "self" => ClosureKind::Fn,
122+
}
123+
124+
ClosureArgs: Vec<Ty> = {
125+
"," <args:FnArgs> => args,
119126
}
120127

121128
TraitDefn: TraitDefn = {

chalk-solve/src/clauses/builtin_traits/copy.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ pub fn add_copy_program_clauses<I: Interner>(
5656
}
5757
TypeName::Closure(closure_id) => {
5858
let upvars = db.closure_upvars(*closure_id, substitution);
59-
needs_impl_for_tys(db, builder, trait_ref, Some(upvars).into_iter());
59+
builder.push_binders(&upvars, |builder, upvars| {
60+
needs_impl_for_tys(db, builder, trait_ref, Some(upvars).into_iter());
61+
})
6062
}
6163
_ => return,
6264
},

0 commit comments

Comments
 (0)