]>
Commit | Line | Data |
---|---|---|
a2a8927a XL |
1 | use crate::clauses::ClauseBuilder; |
2 | use crate::rust_ir::WellKnownTrait; | |
3 | use crate::{Interner, RustIrDatabase, TraitRef}; | |
4 | use chalk_ir::cast::Cast; | |
5 | use chalk_ir::{AliasTy, Floundered, Normalize, ProjectionTy, Substitution, Ty, TyKind}; | |
6 | ||
7 | /// Add implicit impls of the generator trait, i.e., add a clause that all generators implement | |
8 | /// `Generator` and clauses for `Generator`'s associated types. | |
9 | pub fn add_generator_program_clauses<I: Interner>( | |
10 | db: &dyn RustIrDatabase<I>, | |
11 | builder: &mut ClauseBuilder<'_, I>, | |
12 | self_ty: Ty<I>, | |
13 | ) -> Result<(), Floundered> { | |
14 | let interner = db.interner(); | |
15 | ||
16 | match self_ty.kind(interner) { | |
17 | TyKind::Generator(id, substitution) => { | |
18 | let generator_datum = db.generator_datum(*id); | |
19 | let generator_io_datum = generator_datum | |
20 | .input_output | |
21 | .clone() | |
22 | .substitute(interner, &substitution); | |
23 | ||
24 | let trait_id = db.well_known_trait_id(WellKnownTrait::Generator).unwrap(); | |
25 | let trait_datum = db.trait_datum(trait_id); | |
26 | assert_eq!( | |
27 | trait_datum.associated_ty_ids.len(), | |
28 | 2, | |
29 | "Generator trait should have exactly two associated types, found {:?}", | |
30 | trait_datum.associated_ty_ids | |
31 | ); | |
32 | ||
33 | let substitution = Substitution::from_iter( | |
34 | interner, | |
35 | &[ | |
36 | self_ty.cast(interner), | |
37 | generator_io_datum.resume_type.cast(interner), | |
38 | ], | |
39 | ); | |
40 | ||
41 | // generator: Generator<resume_type> | |
42 | builder.push_fact(TraitRef { | |
43 | trait_id, | |
44 | substitution: substitution.clone(), | |
45 | }); | |
46 | ||
47 | // `Generator::Yield` | |
48 | let yield_id = trait_datum.associated_ty_ids[0]; | |
49 | let yield_alias = AliasTy::Projection(ProjectionTy { | |
50 | associated_ty_id: yield_id, | |
51 | substitution: substitution.clone(), | |
52 | }); | |
53 | builder.push_fact(Normalize { | |
54 | alias: yield_alias, | |
55 | ty: generator_io_datum.yield_type, | |
56 | }); | |
57 | ||
58 | // `Generator::Return` | |
59 | let return_id = trait_datum.associated_ty_ids[1]; | |
60 | let return_alias = AliasTy::Projection(ProjectionTy { | |
61 | associated_ty_id: return_id, | |
62 | substitution, | |
63 | }); | |
64 | builder.push_fact(Normalize { | |
65 | alias: return_alias, | |
66 | ty: generator_io_datum.return_type, | |
67 | }); | |
68 | ||
69 | Ok(()) | |
70 | } | |
71 | ||
72 | // Generator trait is non-enumerable | |
73 | TyKind::InferenceVar(..) | TyKind::BoundVar(_) | TyKind::Alias(..) => Err(Floundered), | |
74 | _ => Ok(()), | |
75 | } | |
76 | } |