Skip to content

Commit eaab84b

Browse files
authored
Merge pull request #464 from nathanwhit/opaque-ty-generics
Opaque Type Generics
2 parents da0d8e7 + 5e5e4b1 commit eaab84b

File tree

5 files changed

+133
-53
lines changed

5 files changed

+133
-53
lines changed

chalk-integration/src/lowering.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type OpaqueTyIds = BTreeMap<Ident, chalk_ir::OpaqueTyId<ChalkIr>>;
2525
type AdtKinds = BTreeMap<chalk_ir::AdtId<ChalkIr>, TypeKind>;
2626
type FnDefKinds = BTreeMap<chalk_ir::FnDefId<ChalkIr>, TypeKind>;
2727
type TraitKinds = BTreeMap<chalk_ir::TraitId<ChalkIr>, TypeKind>;
28+
type OpaqueTyKinds = BTreeMap<chalk_ir::OpaqueTyId<ChalkIr>, TypeKind>;
2829
type AssociatedTyLookups = BTreeMap<(chalk_ir::TraitId<ChalkIr>, Ident), AssociatedTyLookup>;
2930
type AssociatedTyValueIds =
3031
BTreeMap<(chalk_ir::ImplId<ChalkIr>, Ident), AssociatedTyValueId<ChalkIr>>;
@@ -42,6 +43,7 @@ struct Env<'k> {
4243
trait_ids: &'k TraitIds,
4344
trait_kinds: &'k TraitKinds,
4445
opaque_ty_ids: &'k OpaqueTyIds,
46+
opaque_ty_kinds: &'k OpaqueTyKinds,
4547
associated_ty_lookups: &'k AssociatedTyLookups,
4648
/// GenericArg identifiers are used as keys, therefore
4749
/// all identifiers in an environment must be unique (no shadowing).
@@ -76,6 +78,7 @@ struct AssociatedTyLookup {
7678
enum ApplyTypeLookup {
7779
Adt(AdtId<ChalkIr>),
7880
FnDef(FnDefId<ChalkIr>),
81+
Opaque(OpaqueTyId<ChalkIr>),
7982
}
8083

8184
const SELF: &str = "Self";
@@ -158,10 +161,6 @@ impl<'k> Env<'k> {
158161
return Err(RustIrError::CannotApplyTypeParameter(name.clone()));
159162
}
160163

161-
if let Some(_) = self.opaque_ty_ids.get(&name.str) {
162-
return Err(RustIrError::CannotApplyTypeParameter(name.clone()));
163-
}
164-
165164
if let Some(id) = self.adt_ids.get(&name.str) {
166165
return Ok(ApplyTypeLookup::Adt(*id));
167166
}
@@ -170,6 +169,10 @@ impl<'k> Env<'k> {
170169
return Ok(ApplyTypeLookup::FnDef(*id));
171170
}
172171

172+
if let Some(id) = self.opaque_ty_ids.get(&name.str) {
173+
return Ok(ApplyTypeLookup::Opaque(*id));
174+
}
175+
173176
Err(RustIrError::NotStruct(name.clone()))
174177
}
175178

@@ -201,6 +204,10 @@ impl<'k> Env<'k> {
201204
&self.fn_def_kinds[&id]
202205
}
203206

207+
fn opaque_kind(&self, id: chalk_ir::OpaqueTyId<ChalkIr>) -> &TypeKind {
208+
&self.opaque_ty_kinds[&id]
209+
}
210+
204211
/// Introduces new parameters, shifting the indices of existing
205212
/// parameters to accommodate them. The indices of the new binders
206213
/// will be assigned in order as they are iterated.
@@ -369,6 +376,7 @@ impl LowerProgram for Program {
369376
trait_ids: &trait_ids,
370377
trait_kinds: &trait_kinds,
371378
opaque_ty_ids: &opaque_ty_ids,
379+
opaque_ty_kinds: &opaque_ty_kinds,
372380
associated_ty_lookups: &associated_ty_lookups,
373381
parameter_map: BTreeMap::new(),
374382
};
@@ -1311,6 +1319,9 @@ impl LowerTy for Ty {
13111319
ApplyTypeLookup::FnDef(id) => {
13121320
(chalk_ir::TypeName::FnDef(id), env.fn_def_kind(id))
13131321
}
1322+
ApplyTypeLookup::Opaque(id) => {
1323+
(chalk_ir::TypeName::OpaqueType(id), env.opaque_kind(id))
1324+
}
13141325
};
13151326

13161327
if k.binders.len(interner) != args.len() {
@@ -1658,6 +1669,7 @@ impl LowerGoal<LoweredProgram> for Goal {
16581669
adt_kinds: &program.adt_kinds,
16591670
fn_def_kinds: &program.fn_def_kinds,
16601671
trait_kinds: &program.trait_kinds,
1672+
opaque_ty_kinds: &program.opaque_ty_kinds,
16611673
associated_ty_lookups: &associated_ty_lookups,
16621674
parameter_map: BTreeMap::new(),
16631675
};

chalk-solve/src/clauses.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,9 +229,22 @@ fn program_clauses_that_could_match<I: Interner>(
229229
}
230230
}
231231
DomainGoal::Holds(WhereClause::AliasEq(alias_eq)) => match &alias_eq.alias {
232-
AliasTy::Projection(proj) => db
233-
.associated_ty_data(proj.associated_ty_id)
234-
.to_program_clauses(builder),
232+
AliasTy::Projection(proj) => {
233+
let trait_self_ty = db
234+
.trait_ref_from_projection(proj)
235+
.self_type_parameter(interner);
236+
237+
if let TyData::Apply(ApplicationTy {
238+
name: TypeName::OpaqueType(opaque_ty_id),
239+
..
240+
}) = trait_self_ty.data(interner)
241+
{
242+
db.opaque_ty_data(*opaque_ty_id).to_program_clauses(builder)
243+
}
244+
245+
db.associated_ty_data(proj.associated_ty_id)
246+
.to_program_clauses(builder)
247+
}
235248
AliasTy::Opaque(opaque_ty) => db
236249
.opaque_ty_data(opaque_ty.opaque_ty_id)
237250
.to_program_clauses(builder),

tests/test/existential_types.rs

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,52 +2,6 @@
22
33
use super::*;
44

5-
#[test]
6-
fn opaque_bounds() {
7-
test! {
8-
program {
9-
struct Ty { }
10-
11-
trait Clone { }
12-
opaque type T: Clone = Ty;
13-
}
14-
15-
goal {
16-
T: Clone
17-
} yields {
18-
"Unique; substitution []"
19-
}
20-
}
21-
}
22-
23-
#[test]
24-
fn opaque_reveal() {
25-
test! {
26-
program {
27-
struct Ty { }
28-
trait Trait { }
29-
impl Trait for Ty { }
30-
31-
trait Clone { }
32-
opaque type T: Clone = Ty;
33-
}
34-
35-
goal {
36-
if (Reveal) {
37-
T: Trait
38-
}
39-
} yields {
40-
"Unique; substitution []"
41-
}
42-
43-
goal {
44-
T: Trait
45-
} yields {
46-
"No possible solution"
47-
}
48-
}
49-
}
50-
515
#[test]
526
fn dyn_Clone_is_Clone() {
537
test! {

tests/test/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@ mod impls;
308308
mod misc;
309309
mod negation;
310310
mod object_safe;
311+
mod opaque_types;
311312
mod projection;
312313
mod refs;
313314
mod scalars;

tests/test/opaque_types.rs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
use super::*;
2+
3+
#[test]
4+
fn opaque_bounds() {
5+
test! {
6+
program {
7+
struct Ty { }
8+
9+
trait Clone { }
10+
opaque type T: Clone = Ty;
11+
}
12+
13+
goal {
14+
T: Clone
15+
} yields {
16+
"Unique; substitution []"
17+
}
18+
}
19+
}
20+
21+
#[test]
22+
fn opaque_reveal() {
23+
test! {
24+
program {
25+
struct Ty { }
26+
trait Trait { }
27+
impl Trait for Ty { }
28+
29+
trait Clone { }
30+
opaque type T: Clone = Ty;
31+
}
32+
33+
goal {
34+
if (Reveal) {
35+
T: Trait
36+
}
37+
} yields {
38+
"Unique; substitution []"
39+
}
40+
41+
goal {
42+
T: Trait
43+
} yields {
44+
"No possible solution"
45+
}
46+
}
47+
}
48+
49+
#[test]
50+
fn opaque_generics_simple() {
51+
test! {
52+
program {
53+
trait Iterator { type Item; }
54+
55+
struct Vec<T> { }
56+
struct Bar { }
57+
impl<T> Iterator for Vec<T> {
58+
type Item = u32;
59+
}
60+
61+
opaque type Foo<X>: Iterator = Vec<X>;
62+
}
63+
64+
goal {
65+
Foo<Bar>: Iterator
66+
} yields {
67+
"Unique; substitution []"
68+
}
69+
70+
}
71+
}
72+
73+
#[test]
74+
fn opaque_generics() {
75+
test! {
76+
program {
77+
trait Iterator { type Item; }
78+
79+
struct Vec<T> { }
80+
struct Bar { }
81+
82+
opaque type Foo<X>: Iterator<Item = X> = Vec<X>;
83+
}
84+
85+
goal {
86+
Foo<Bar>: Iterator<Item = Bar>
87+
} yields {
88+
"Unique; substitution []"
89+
}
90+
91+
goal {
92+
forall<T> {
93+
Foo<T>: Iterator<Item = T>
94+
}
95+
} yields {
96+
"Unique; substitution []"
97+
}
98+
99+
}
100+
}

0 commit comments

Comments
 (0)