11use chalk_ir:: cast:: { Cast , Caster } ;
22use chalk_ir:: interner:: ChalkIr ;
33use 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 ,
66} ;
77use chalk_parse:: ast:: * ;
88use 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+ } ;
1013use lalrpop_intern:: intern;
1114use std:: collections:: BTreeMap ;
1215use std:: sync:: Arc ;
@@ -17,6 +20,7 @@ use crate::{Identifier as Ident, RawId, TypeKind, TypeSort};
1720
1821type StructIds = BTreeMap < Ident , chalk_ir:: StructId < ChalkIr > > ;
1922type TraitIds = BTreeMap < Ident , chalk_ir:: TraitId < ChalkIr > > ;
23+ type OpaqueTyIds = BTreeMap < Ident , chalk_ir:: OpaqueTyId < ChalkIr > > ;
2024type StructKinds = BTreeMap < chalk_ir:: StructId < ChalkIr > , TypeKind > ;
2125type TraitKinds = BTreeMap < chalk_ir:: TraitId < ChalkIr > , TypeKind > ;
2226type AssociatedTyLookups = BTreeMap < ( chalk_ir:: TraitId < ChalkIr > , Ident ) , AssociatedTyLookup > ;
@@ -32,6 +36,7 @@ struct Env<'k> {
3236 struct_kinds : & ' k StructKinds ,
3337 trait_ids : & ' k TraitIds ,
3438 trait_kinds : & ' k TraitKinds ,
39+ opaque_ty_ids : & ' k OpaqueTyIds ,
3540 associated_ty_lookups : & ' k AssociatedTyLookups ,
3641 /// Parameter identifiers are used as keys, therefore
3742 /// all identifiers in an environment must be unique (no shadowing).
@@ -66,6 +71,7 @@ struct AssociatedTyLookup {
6671enum TypeLookup {
6772 Struct ( chalk_ir:: StructId < ChalkIr > ) ,
6873 Parameter ( BoundVar ) ,
74+ Opaque ( chalk_ir:: OpaqueTyId < ChalkIr > ) ,
6975}
7076
7177enum LifetimeLookup {
@@ -88,6 +94,9 @@ impl<'k> Env<'k> {
8894 return Ok ( TypeLookup :: Struct ( * id) ) ;
8995 }
9096
97+ if let Some ( id) = self . opaque_ty_ids . get ( & name. str ) {
98+ return Ok ( TypeLookup :: Opaque ( * id) ) ;
99+ }
91100 if let Some ( _) = self . trait_ids . get ( & name. str ) {
92101 return Err ( RustIrError :: NotStruct ( name) ) ;
93102 }
@@ -223,8 +232,10 @@ impl LowerProgram for Program {
223232
224233 let mut struct_ids = BTreeMap :: new ( ) ;
225234 let mut trait_ids = BTreeMap :: new ( ) ;
235+ let mut opaque_ty_ids = BTreeMap :: new ( ) ;
226236 let mut struct_kinds = BTreeMap :: new ( ) ;
227237 let mut trait_kinds = BTreeMap :: new ( ) ;
238+ let mut opaque_ty_kinds = BTreeMap :: new ( ) ;
228239 for ( item, & raw_id) in self . items . iter ( ) . zip ( & raw_ids) {
229240 match item {
230241 Item :: StructDefn ( defn) => {
@@ -239,6 +250,12 @@ impl LowerProgram for Program {
239250 trait_ids. insert ( type_kind. name , id) ;
240251 trait_kinds. insert ( id, type_kind) ;
241252 }
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+ }
242259 Item :: Impl ( _) => continue ,
243260 Item :: Clause ( _) => continue ,
244261 } ;
@@ -250,13 +267,15 @@ impl LowerProgram for Program {
250267 let mut impl_data = BTreeMap :: new ( ) ;
251268 let mut associated_ty_data = BTreeMap :: new ( ) ;
252269 let mut associated_ty_values = BTreeMap :: new ( ) ;
270+ let mut opaque_ty_data = BTreeMap :: new ( ) ;
253271 let mut custom_clauses = Vec :: new ( ) ;
254272 for ( item, & raw_id) in self . items . iter ( ) . zip ( & raw_ids) {
255273 let empty_env = Env {
256274 struct_ids : & struct_ids,
257275 struct_kinds : & struct_kinds,
258276 trait_ids : & trait_ids,
259277 trait_kinds : & trait_kinds,
278+ opaque_ty_ids : & opaque_ty_ids,
260279 associated_ty_lookups : & associated_ty_lookups,
261280 parameter_map : BTreeMap :: new ( ) ,
262281 } ;
@@ -361,6 +380,57 @@ impl LowerProgram for Program {
361380 Item :: Clause ( ref clause) => {
362381 custom_clauses. extend ( clause. lower_clause ( & empty_env) ?) ;
363382 }
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+ }
364434 }
365435 }
366436
@@ -375,6 +445,8 @@ impl LowerProgram for Program {
375445 impl_data,
376446 associated_ty_values,
377447 associated_ty_data,
448+ opaque_ty_ids,
449+ opaque_ty_data,
378450 custom_clauses,
379451 } ;
380452
@@ -551,6 +623,17 @@ impl LowerTypeKind for TraitDefn {
551623 }
552624}
553625
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+
554637impl LowerWhereClauses for TraitDefn {
555638 fn where_clauses ( & self ) -> & [ QuantifiedWhereClause ] {
556639 & self . where_clauses
@@ -582,7 +665,7 @@ trait LowerWhereClause<T> {
582665 /// Lower from an AST `where` clause to an internal IR.
583666 /// Some AST `where` clauses can lower to multiple ones, this is why we return a `Vec`.
584667 /// 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)`.
586669 fn lower ( & self , env : & Env ) -> LowerResult < Vec < T > > ;
587670}
588671
@@ -592,12 +675,12 @@ impl LowerWhereClause<chalk_ir::WhereClause<ChalkIr>> for WhereClause {
592675 WhereClause :: Implemented { trait_ref } => {
593676 vec ! [ chalk_ir:: WhereClause :: Implemented ( trait_ref. lower( env) ?) ]
594677 }
595- WhereClause :: AliasEq { alias , ty } => vec ! [
678+ WhereClause :: ProjectionEq { projection , ty } => vec ! [
596679 chalk_ir:: WhereClause :: AliasEq ( chalk_ir:: AliasEq {
597- alias: alias . lower( env) ?,
680+ alias: chalk_ir :: AliasTy :: Projection ( projection . lower( env) ?) ,
598681 ty: ty. lower( env) ?,
599682 } ) ,
600- chalk_ir:: WhereClause :: Implemented ( alias . trait_ref. lower( env) ?) ,
683+ chalk_ir:: WhereClause :: Implemented ( projection . trait_ref. lower( env) ?) ,
601684 ] ,
602685 } ;
603686 Ok ( where_clauses)
@@ -624,9 +707,9 @@ impl LowerDomainGoal for DomainGoal {
624707 . into_iter ( )
625708 . casted ( interner)
626709 . collect ( ) ,
627- DomainGoal :: Normalize { alias , ty } => {
710+ DomainGoal :: Normalize { projection , ty } => {
628711 vec ! [ chalk_ir:: DomainGoal :: Normalize ( chalk_ir:: Normalize {
629- alias: alias . lower( env) ?,
712+ alias: chalk_ir :: AliasTy :: Projection ( projection . lower( env) ?) ,
630713 ty: ty. lower( env) ?,
631714 } ) ]
632715 }
@@ -656,6 +739,7 @@ impl LowerDomainGoal for DomainGoal {
656739 DomainGoal :: DownstreamType { ty } => {
657740 vec ! [ chalk_ir:: DomainGoal :: DownstreamType ( ty. lower( env) ?) ]
658741 }
742+ DomainGoal :: Reveal => vec ! [ chalk_ir:: DomainGoal :: Reveal ( ( ) ) ] ,
659743 } ;
660744 Ok ( goals)
661745 }
@@ -915,13 +999,13 @@ impl LowerTraitFlags for TraitFlags {
915999 }
9161000}
9171001
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 > > ;
9201004}
9211005
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 {
9251009 ref trait_ref,
9261010 ref name,
9271011 ref args,
@@ -960,7 +1044,7 @@ impl LowerAliasTy for AliasTy {
9601044
9611045 args. extend ( trait_substitution. iter ( interner) . cloned ( ) ) ;
9621046
963- Ok ( chalk_ir:: AliasTy {
1047+ Ok ( chalk_ir:: ProjectionTy {
9641048 associated_ty_id : lookup. id ,
9651049 substitution : chalk_ir:: Substitution :: from ( interner, args) ,
9661050 } )
@@ -993,6 +1077,13 @@ impl LowerTy for Ty {
9931077 }
9941078 }
9951079 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) ) ,
9961087 } ,
9971088
9981089 Ty :: Dyn { ref bounds } => Ok ( chalk_ir:: TyData :: Dyn ( chalk_ir:: DynTy {
@@ -1021,7 +1112,9 @@ impl LowerTy for Ty {
10211112 Ty :: Apply { name, ref args } => {
10221113 let id = match env. lookup_type ( name) ? {
10231114 TypeLookup :: Struct ( id) => id,
1024- TypeLookup :: Parameter ( _) => Err ( RustIrError :: CannotApplyTypeParameter ( name) ) ?,
1115+ TypeLookup :: Parameter ( _) | TypeLookup :: Opaque ( _) => {
1116+ Err ( RustIrError :: CannotApplyTypeParameter ( name) ) ?
1117+ }
10251118 } ;
10261119
10271120 let k = env. struct_kind ( id) ;
@@ -1055,9 +1148,10 @@ impl LowerTy for Ty {
10551148 . intern ( interner) )
10561149 }
10571150
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) ) ,
10611155
10621156 Ty :: ForAll {
10631157 ref lifetime_names,
@@ -1287,6 +1381,7 @@ impl LowerGoal<LoweredProgram> for Goal {
12871381 let env = Env {
12881382 struct_ids : & program. struct_ids ,
12891383 trait_ids : & program. trait_ids ,
1384+ opaque_ty_ids : & program. opaque_ty_ids ,
12901385 struct_kinds : & program. struct_kinds ,
12911386 trait_kinds : & program. trait_kinds ,
12921387 associated_ty_lookups : & associated_ty_lookups,
0 commit comments