1
1
use chalk_ir:: cast:: { Cast , Caster } ;
2
2
use chalk_ir:: interner:: ChalkIr ;
3
3
use chalk_ir:: {
4
- self , AssocTypeId , BoundVar , ClausePriority , DebruijnIndex , ImplId , QuantifiedWhereClauses ,
5
- StructId , Substitution , TraitId ,
4
+ self , AssocTypeId , BoundVar , ClausePriority , DebruijnIndex , ImplId , OpaqueTyId ,
5
+ QuantifiedWhereClauses , StructId , Substitution , TraitId ,
6
6
} ;
7
7
use chalk_parse:: ast:: * ;
8
8
use chalk_rust_ir as rust_ir;
9
- use chalk_rust_ir:: { Anonymize , AssociatedTyValueId , IntoWhereClauses , ToParameter } ;
9
+ use chalk_rust_ir:: {
10
+ Anonymize , AssociatedTyValueId , IntoWhereClauses , OpaqueTyDatum , OpaqueTyDatumBound ,
11
+ ToParameter ,
12
+ } ;
10
13
use lalrpop_intern:: intern;
11
14
use std:: collections:: BTreeMap ;
12
15
use std:: sync:: Arc ;
@@ -17,6 +20,7 @@ use crate::{Identifier as Ident, RawId, TypeKind, TypeSort};
17
20
18
21
type StructIds = BTreeMap < Ident , chalk_ir:: StructId < ChalkIr > > ;
19
22
type TraitIds = BTreeMap < Ident , chalk_ir:: TraitId < ChalkIr > > ;
23
+ type OpaqueTyIds = BTreeMap < Ident , chalk_ir:: OpaqueTyId < ChalkIr > > ;
20
24
type StructKinds = BTreeMap < chalk_ir:: StructId < ChalkIr > , TypeKind > ;
21
25
type TraitKinds = BTreeMap < chalk_ir:: TraitId < ChalkIr > , TypeKind > ;
22
26
type AssociatedTyLookups = BTreeMap < ( chalk_ir:: TraitId < ChalkIr > , Ident ) , AssociatedTyLookup > ;
@@ -32,6 +36,7 @@ struct Env<'k> {
32
36
struct_kinds : & ' k StructKinds ,
33
37
trait_ids : & ' k TraitIds ,
34
38
trait_kinds : & ' k TraitKinds ,
39
+ opaque_ty_ids : & ' k OpaqueTyIds ,
35
40
associated_ty_lookups : & ' k AssociatedTyLookups ,
36
41
/// Parameter identifiers are used as keys, therefore
37
42
/// all identifiers in an environment must be unique (no shadowing).
@@ -66,6 +71,7 @@ struct AssociatedTyLookup {
66
71
enum TypeLookup {
67
72
Struct ( chalk_ir:: StructId < ChalkIr > ) ,
68
73
Parameter ( BoundVar ) ,
74
+ Opaque ( chalk_ir:: OpaqueTyId < ChalkIr > ) ,
69
75
}
70
76
71
77
enum LifetimeLookup {
@@ -88,6 +94,9 @@ impl<'k> Env<'k> {
88
94
return Ok ( TypeLookup :: Struct ( * id) ) ;
89
95
}
90
96
97
+ if let Some ( id) = self . opaque_ty_ids . get ( & name. str ) {
98
+ return Ok ( TypeLookup :: Opaque ( * id) ) ;
99
+ }
91
100
if let Some ( _) = self . trait_ids . get ( & name. str ) {
92
101
return Err ( RustIrError :: NotStruct ( name) ) ;
93
102
}
@@ -223,8 +232,10 @@ impl LowerProgram for Program {
223
232
224
233
let mut struct_ids = BTreeMap :: new ( ) ;
225
234
let mut trait_ids = BTreeMap :: new ( ) ;
235
+ let mut opaque_ty_ids = BTreeMap :: new ( ) ;
226
236
let mut struct_kinds = BTreeMap :: new ( ) ;
227
237
let mut trait_kinds = BTreeMap :: new ( ) ;
238
+ let mut opaque_ty_kinds = BTreeMap :: new ( ) ;
228
239
for ( item, & raw_id) in self . items . iter ( ) . zip ( & raw_ids) {
229
240
match item {
230
241
Item :: StructDefn ( defn) => {
@@ -239,6 +250,12 @@ impl LowerProgram for Program {
239
250
trait_ids. insert ( type_kind. name , id) ;
240
251
trait_kinds. insert ( id, type_kind) ;
241
252
}
253
+ Item :: OpaqueTyDefn ( defn) => {
254
+ let type_kind = defn. lower_type_kind ( ) ?;
255
+ let id = OpaqueTyId ( raw_id) ;
256
+ opaque_ty_ids. insert ( defn. identifier . str , id) ;
257
+ opaque_ty_kinds. insert ( id, type_kind) ;
258
+ }
242
259
Item :: Impl ( _) => continue ,
243
260
Item :: Clause ( _) => continue ,
244
261
} ;
@@ -250,13 +267,15 @@ impl LowerProgram for Program {
250
267
let mut impl_data = BTreeMap :: new ( ) ;
251
268
let mut associated_ty_data = BTreeMap :: new ( ) ;
252
269
let mut associated_ty_values = BTreeMap :: new ( ) ;
270
+ let mut opaque_ty_data = BTreeMap :: new ( ) ;
253
271
let mut custom_clauses = Vec :: new ( ) ;
254
272
for ( item, & raw_id) in self . items . iter ( ) . zip ( & raw_ids) {
255
273
let empty_env = Env {
256
274
struct_ids : & struct_ids,
257
275
struct_kinds : & struct_kinds,
258
276
trait_ids : & trait_ids,
259
277
trait_kinds : & trait_kinds,
278
+ opaque_ty_ids : & opaque_ty_ids,
260
279
associated_ty_lookups : & associated_ty_lookups,
261
280
parameter_map : BTreeMap :: new ( ) ,
262
281
} ;
@@ -361,6 +380,57 @@ impl LowerProgram for Program {
361
380
Item :: Clause ( ref clause) => {
362
381
custom_clauses. extend ( clause. lower_clause ( & empty_env) ?) ;
363
382
}
383
+ Item :: OpaqueTyDefn ( ref opaque_ty) => {
384
+ if let Some ( & opaque_ty_id) = opaque_ty_ids. get ( & opaque_ty. identifier . str ) {
385
+ let parameter_kinds = opaque_ty
386
+ . parameter_kinds
387
+ . iter ( )
388
+ . map ( |k| k. lower ( ) )
389
+ . collect :: < Vec < _ > > ( ) ;
390
+
391
+ // Introduce the parameters declared on the opaque type definition.
392
+ // So if we have `type Foo<P1..Pn> = impl Trait<T1..Tn>`, this would introduce `P1..Pn`
393
+ let binders = empty_env. in_binders ( parameter_kinds, |env| {
394
+ let hidden_ty = opaque_ty. ty . lower ( & env) ?;
395
+
396
+ // Introduce a variable to represent the hidden "self type". This will be used in the bounds.
397
+ // So the `impl Trait<T1..Tn>` will be lowered to `exists<Self> { Self: Trait<T1..Tn> }`.
398
+ let bounds: chalk_ir:: Binders < Vec < chalk_ir:: Binders < _ > > > = env
399
+ . in_binders (
400
+ Some ( chalk_ir:: ParameterKind :: Ty ( intern ( FIXME_SELF ) ) ) ,
401
+ |env1| {
402
+ let interner = env1. interner ( ) ;
403
+ Ok ( opaque_ty
404
+ . bounds
405
+ . lower ( & env1) ?
406
+ . iter ( )
407
+ . flat_map ( |qil| {
408
+ // Instantiate the bounds with the innermost bound variable, which represents Self, as the self type.
409
+ qil. into_where_clauses (
410
+ interner,
411
+ chalk_ir:: TyData :: BoundVar ( BoundVar :: new (
412
+ DebruijnIndex :: INNERMOST ,
413
+ 0 ,
414
+ ) )
415
+ . intern ( interner) ,
416
+ )
417
+ } )
418
+ . collect ( ) )
419
+ } ,
420
+ ) ?;
421
+
422
+ Ok ( OpaqueTyDatumBound { hidden_ty, bounds } )
423
+ } ) ?;
424
+
425
+ opaque_ty_data. insert (
426
+ opaque_ty_id,
427
+ Arc :: new ( OpaqueTyDatum {
428
+ opaque_ty_id,
429
+ bound : binders,
430
+ } ) ,
431
+ ) ;
432
+ }
433
+ }
364
434
}
365
435
}
366
436
@@ -375,6 +445,8 @@ impl LowerProgram for Program {
375
445
impl_data,
376
446
associated_ty_values,
377
447
associated_ty_data,
448
+ opaque_ty_ids,
449
+ opaque_ty_data,
378
450
custom_clauses,
379
451
} ;
380
452
@@ -551,6 +623,17 @@ impl LowerTypeKind for TraitDefn {
551
623
}
552
624
}
553
625
626
+ impl LowerTypeKind for OpaqueTyDefn {
627
+ fn lower_type_kind ( & self ) -> LowerResult < TypeKind > {
628
+ let binders: Vec < _ > = self . parameter_kinds . iter ( ) . map ( |p| p. lower ( ) ) . collect ( ) ;
629
+ Ok ( TypeKind {
630
+ sort : TypeSort :: Opaque ,
631
+ name : self . identifier . str ,
632
+ binders : chalk_ir:: Binders :: new ( binders. anonymize ( ) , ( ) ) ,
633
+ } )
634
+ }
635
+ }
636
+
554
637
impl LowerWhereClauses for TraitDefn {
555
638
fn where_clauses ( & self ) -> & [ QuantifiedWhereClause ] {
556
639
& self . where_clauses
@@ -582,7 +665,7 @@ trait LowerWhereClause<T> {
582
665
/// Lower from an AST `where` clause to an internal IR.
583
666
/// Some AST `where` clauses can lower to multiple ones, this is why we return a `Vec`.
584
667
/// As for now, this is the only the case for `where T: Foo<Item = U>` which lowers to
585
- /// `Implemented(T: Foo)` and `AliasEq (<T as Foo>::Item = U)`.
668
+ /// `Implemented(T: Foo)` and `ProjectionEq (<T as Foo>::Item = U)`.
586
669
fn lower ( & self , env : & Env ) -> LowerResult < Vec < T > > ;
587
670
}
588
671
@@ -592,12 +675,12 @@ impl LowerWhereClause<chalk_ir::WhereClause<ChalkIr>> for WhereClause {
592
675
WhereClause :: Implemented { trait_ref } => {
593
676
vec ! [ chalk_ir:: WhereClause :: Implemented ( trait_ref. lower( env) ?) ]
594
677
}
595
- WhereClause :: AliasEq { alias , ty } => vec ! [
678
+ WhereClause :: ProjectionEq { projection , ty } => vec ! [
596
679
chalk_ir:: WhereClause :: AliasEq ( chalk_ir:: AliasEq {
597
- alias: alias . lower( env) ?,
680
+ alias: chalk_ir :: AliasTy :: Projection ( projection . lower( env) ?) ,
598
681
ty: ty. lower( env) ?,
599
682
} ) ,
600
- chalk_ir:: WhereClause :: Implemented ( alias . trait_ref. lower( env) ?) ,
683
+ chalk_ir:: WhereClause :: Implemented ( projection . trait_ref. lower( env) ?) ,
601
684
] ,
602
685
} ;
603
686
Ok ( where_clauses)
@@ -624,9 +707,9 @@ impl LowerDomainGoal for DomainGoal {
624
707
. into_iter ( )
625
708
. casted ( interner)
626
709
. collect ( ) ,
627
- DomainGoal :: Normalize { alias , ty } => {
710
+ DomainGoal :: Normalize { projection , ty } => {
628
711
vec ! [ chalk_ir:: DomainGoal :: Normalize ( chalk_ir:: Normalize {
629
- alias: alias . lower( env) ?,
712
+ alias: chalk_ir :: AliasTy :: Projection ( projection . lower( env) ?) ,
630
713
ty: ty. lower( env) ?,
631
714
} ) ]
632
715
}
@@ -656,6 +739,7 @@ impl LowerDomainGoal for DomainGoal {
656
739
DomainGoal :: DownstreamType { ty } => {
657
740
vec ! [ chalk_ir:: DomainGoal :: DownstreamType ( ty. lower( env) ?) ]
658
741
}
742
+ DomainGoal :: Reveal => vec ! [ chalk_ir:: DomainGoal :: Reveal ( ( ) ) ] ,
659
743
} ;
660
744
Ok ( goals)
661
745
}
@@ -915,13 +999,13 @@ impl LowerTraitFlags for TraitFlags {
915
999
}
916
1000
}
917
1001
918
- trait LowerAliasTy {
919
- fn lower ( & self , env : & Env ) -> LowerResult < chalk_ir:: AliasTy < ChalkIr > > ;
1002
+ trait LowerProjectionTy {
1003
+ fn lower ( & self , env : & Env ) -> LowerResult < chalk_ir:: ProjectionTy < ChalkIr > > ;
920
1004
}
921
1005
922
- impl LowerAliasTy for AliasTy {
923
- fn lower ( & self , env : & Env ) -> LowerResult < chalk_ir:: AliasTy < ChalkIr > > {
924
- let AliasTy {
1006
+ impl LowerProjectionTy for ProjectionTy {
1007
+ fn lower ( & self , env : & Env ) -> LowerResult < chalk_ir:: ProjectionTy < ChalkIr > > {
1008
+ let ProjectionTy {
925
1009
ref trait_ref,
926
1010
ref name,
927
1011
ref args,
@@ -960,7 +1044,7 @@ impl LowerAliasTy for AliasTy {
960
1044
961
1045
args. extend ( trait_substitution. iter ( interner) . cloned ( ) ) ;
962
1046
963
- Ok ( chalk_ir:: AliasTy {
1047
+ Ok ( chalk_ir:: ProjectionTy {
964
1048
associated_ty_id : lookup. id ,
965
1049
substitution : chalk_ir:: Substitution :: from ( interner, args) ,
966
1050
} )
@@ -993,6 +1077,13 @@ impl LowerTy for Ty {
993
1077
}
994
1078
}
995
1079
TypeLookup :: Parameter ( d) => Ok ( chalk_ir:: TyData :: BoundVar ( d) . intern ( interner) ) ,
1080
+ TypeLookup :: Opaque ( id) => Ok ( chalk_ir:: TyData :: Alias ( chalk_ir:: AliasTy :: Opaque (
1081
+ chalk_ir:: OpaqueTy {
1082
+ opaque_ty_id : id,
1083
+ substitution : chalk_ir:: Substitution :: empty ( interner) ,
1084
+ } ,
1085
+ ) )
1086
+ . intern ( interner) ) ,
996
1087
} ,
997
1088
998
1089
Ty :: Dyn { ref bounds } => Ok ( chalk_ir:: TyData :: Dyn ( chalk_ir:: DynTy {
@@ -1021,7 +1112,9 @@ impl LowerTy for Ty {
1021
1112
Ty :: Apply { name, ref args } => {
1022
1113
let id = match env. lookup_type ( name) ? {
1023
1114
TypeLookup :: Struct ( id) => id,
1024
- TypeLookup :: Parameter ( _) => Err ( RustIrError :: CannotApplyTypeParameter ( name) ) ?,
1115
+ TypeLookup :: Parameter ( _) | TypeLookup :: Opaque ( _) => {
1116
+ Err ( RustIrError :: CannotApplyTypeParameter ( name) ) ?
1117
+ }
1025
1118
} ;
1026
1119
1027
1120
let k = env. struct_kind ( id) ;
@@ -1055,9 +1148,10 @@ impl LowerTy for Ty {
1055
1148
. intern ( interner) )
1056
1149
}
1057
1150
1058
- Ty :: Alias { ref alias } => {
1059
- Ok ( chalk_ir:: TyData :: Alias ( alias. lower ( env) ?) . intern ( interner) )
1060
- }
1151
+ Ty :: Projection { ref proj } => Ok ( chalk_ir:: TyData :: Alias (
1152
+ chalk_ir:: AliasTy :: Projection ( proj. lower ( env) ?) ,
1153
+ )
1154
+ . intern ( interner) ) ,
1061
1155
1062
1156
Ty :: ForAll {
1063
1157
ref lifetime_names,
@@ -1287,6 +1381,7 @@ impl LowerGoal<LoweredProgram> for Goal {
1287
1381
let env = Env {
1288
1382
struct_ids : & program. struct_ids ,
1289
1383
trait_ids : & program. trait_ids ,
1384
+ opaque_ty_ids : & program. opaque_ty_ids ,
1290
1385
struct_kinds : & program. struct_kinds ,
1291
1386
trait_kinds : & program. trait_kinds ,
1292
1387
associated_ty_lookups : & associated_ty_lookups,
0 commit comments