@@ -9,8 +9,8 @@ use chalk_ir::{
99 AdtId , BoundVar , DebruijnIndex , Scalar ,
1010} ;
1111use hir_def:: {
12- builtin_type:: BuiltinType , generics:: TypeOrConstParamData , ConstParamId , GenericDefId , TraitId ,
13- TypeAliasId ,
12+ builtin_type:: BuiltinType , generics:: TypeOrConstParamData , ConstParamId , DefWithBodyId ,
13+ GenericDefId , TraitId , TypeAliasId ,
1414} ;
1515use smallvec:: SmallVec ;
1616
@@ -205,6 +205,38 @@ impl TyBuilder<()> {
205205 )
206206 }
207207
208+ /// Creates a `TyBuilder` to build `Substitution` for a generator defined in `parent`.
209+ ///
210+ /// A generator's substitution consists of:
211+ /// - generic parameters in scope on `parent`
212+ /// - resume type of generator
213+ /// - yield type of generator ([`Generator::Yield`](std::ops::Generator::Yield))
214+ /// - return type of generator ([`Generator::Return`](std::ops::Generator::Return))
215+ /// in this order.
216+ ///
217+ /// This method prepopulates the builder with placeholder substitution of `parent`, so you
218+ /// should only push exactly 3 `GenericArg`s before building.
219+ pub fn subst_for_generator ( db : & dyn HirDatabase , parent : DefWithBodyId ) -> TyBuilder < ( ) > {
220+ let parent_subst = match parent. as_generic_def_id ( ) {
221+ Some ( parent) => generics ( db. upcast ( ) , parent) . placeholder_subst ( db) ,
222+ // Static initializers *may* contain generators.
223+ None => Substitution :: empty ( Interner ) ,
224+ } ;
225+ let builder = TyBuilder :: new (
226+ ( ) ,
227+ parent_subst
228+ . iter ( Interner )
229+ . map ( |arg| match arg. constant ( Interner ) {
230+ Some ( c) => ParamKind :: Const ( c. data ( Interner ) . ty . clone ( ) ) ,
231+ None => ParamKind :: Type ,
232+ } )
233+ // These represent resume type, yield type, and return type of generator.
234+ . chain ( std:: iter:: repeat ( ParamKind :: Type ) . take ( 3 ) )
235+ . collect ( ) ,
236+ ) ;
237+ builder. use_parent_substs ( & parent_subst)
238+ }
239+
208240 pub fn build ( self ) -> Substitution {
209241 let ( ( ) , subst) = self . build_internal ( ) ;
210242 subst
0 commit comments