diff options
| author | Ryo Yoshida <low.ryoshida@gmail.com> | 2022-09-09 15:20:18 +0900 |
|---|---|---|
| committer | Ryo Yoshida <low.ryoshida@gmail.com> | 2022-09-09 16:49:09 +0900 |
| commit | aeeb9e08b252b24c7cdba0a30e8dd153231c082d (patch) | |
| tree | 17e8091d8a1c8f69f7abe6f73c9e8a97d06df5d1 | |
| parent | ba64c93a44c5bdd78b01ef868435dc427f0cf4d4 (diff) | |
| download | rust-aeeb9e08b252b24c7cdba0a30e8dd153231c082d.tar.gz rust-aeeb9e08b252b24c7cdba0a30e8dd153231c082d.zip | |
Add `TyBuilder` method to build `Substitution` for generator
| -rw-r--r-- | crates/hir-ty/src/builder.rs | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/crates/hir-ty/src/builder.rs b/crates/hir-ty/src/builder.rs index 94d7806cb6e..3ae7fb2a617 100644 --- a/crates/hir-ty/src/builder.rs +++ b/crates/hir-ty/src/builder.rs @@ -9,8 +9,8 @@ use chalk_ir::{ AdtId, BoundVar, DebruijnIndex, Scalar, }; use hir_def::{ - builtin_type::BuiltinType, generics::TypeOrConstParamData, ConstParamId, GenericDefId, TraitId, - TypeAliasId, + builtin_type::BuiltinType, generics::TypeOrConstParamData, ConstParamId, DefWithBodyId, + GenericDefId, TraitId, TypeAliasId, }; use smallvec::SmallVec; @@ -205,6 +205,38 @@ impl TyBuilder<()> { ) } + /// Creates a `TyBuilder` to build `Substitution` for a generator defined in `parent`. + /// + /// A generator's substitution consists of: + /// - generic parameters in scope on `parent` + /// - resume type of generator + /// - yield type of generator ([`Generator::Yield`](std::ops::Generator::Yield)) + /// - return type of generator ([`Generator::Return`](std::ops::Generator::Return)) + /// in this order. + /// + /// This method prepopulates the builder with placeholder substitution of `parent`, so you + /// should only push exactly 3 `GenericArg`s before building. + pub fn subst_for_generator(db: &dyn HirDatabase, parent: DefWithBodyId) -> TyBuilder<()> { + let parent_subst = match parent.as_generic_def_id() { + Some(parent) => generics(db.upcast(), parent).placeholder_subst(db), + // Static initializers *may* contain generators. + None => Substitution::empty(Interner), + }; + let builder = TyBuilder::new( + (), + parent_subst + .iter(Interner) + .map(|arg| match arg.constant(Interner) { + Some(c) => ParamKind::Const(c.data(Interner).ty.clone()), + None => ParamKind::Type, + }) + // These represent resume type, yield type, and return type of generator. + .chain(std::iter::repeat(ParamKind::Type).take(3)) + .collect(), + ); + builder.use_parent_substs(&parent_subst) + } + pub fn build(self) -> Substitution { let ((), subst) = self.build_internal(); subst |
