Skip to content

Commit e27bc3f

Browse files
committed
Expand test
1 parent 70a4c2b commit e27bc3f

File tree

7 files changed

+107
-27
lines changed

7 files changed

+107
-27
lines changed

chalk-integration/src/lowering.rs

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ enum ApplyTypeLookup {
8888
Adt(AdtId<ChalkIr>),
8989
FnDef(FnDefId<ChalkIr>),
9090
Closure(ClosureId<ChalkIr>),
91+
Generator(GeneratorId<ChalkIr>),
9192
Opaque(OpaqueTyId<ChalkIr>),
9293
}
9394

@@ -220,6 +221,10 @@ impl<'k> Env<'k> {
220221
return Ok(ApplyTypeLookup::Closure(*id));
221222
}
222223

224+
if let Some(id) = self.generator_ids.get(&name.str) {
225+
return Ok(ApplyTypeLookup::Generator(*id));
226+
}
227+
223228
if let Some(id) = self.opaque_ty_ids.get(&name.str) {
224229
return Ok(ApplyTypeLookup::Opaque(*id));
225230
}
@@ -1306,11 +1311,13 @@ impl LowerGeneratorDefn for GeneratorDefn {
13061311
let yield_type = self.yield_ty.lower(env)?;
13071312
let resume_type = self.resume_ty.lower(env)?;
13081313
let return_type = self.return_ty.lower(env)?;
1314+
let upvars: LowerResult<_> = self.upvars.iter().map(|ty| ty.lower(env)).collect();
13091315

13101316
Ok(rust_ir::GeneratorInputOutputDatum {
13111317
resume_type,
13121318
yield_type,
13131319
return_type,
1320+
upvars: upvars?
13141321
})
13151322
})?;
13161323

@@ -1326,31 +1333,6 @@ impl LowerGeneratorDefn for GeneratorDefn {
13261333
}
13271334
}
13281335

1329-
trait LowerGeneratorInputOutputDatum {
1330-
fn lower_generator_input_output_datum(
1331-
&self,
1332-
env: &Env
1333-
) -> LowerResult<chalk_ir::Binders<rust_ir::GeneratorInputOutputDatum<ChalkIr>>>;
1334-
}
1335-
1336-
impl LowerGeneratorInputOutputDatum for GeneratorDefn {
1337-
fn lower_generator_input_output_datum(
1338-
&self,
1339-
env: &Env
1340-
) -> LowerResult<chalk_ir::Binders<rust_ir::GeneratorInputOutputDatum<ChalkIr>>> {
1341-
env.in_binders(self.all_parameters(), |env| {
1342-
let resume_type = self.resume_ty.lower(env)?;
1343-
let yield_type = self.yield_ty.lower(env)?;
1344-
let return_type = self.return_ty.lower(env)?;
1345-
Ok(rust_ir::GeneratorInputOutputDatum {
1346-
resume_type,
1347-
yield_type,
1348-
return_type
1349-
})
1350-
})
1351-
}
1352-
}
1353-
13541336
trait LowerClosureKind {
13551337
fn lower_closure_kind(&self) -> LowerResult<rust_ir::ClosureKind>;
13561338
}
@@ -1689,6 +1671,9 @@ impl LowerTy for Ty {
16891671
ApplyTypeLookup::FnDef(id) => {
16901672
(chalk_ir::TypeName::FnDef(id), env.fn_def_kind(id))
16911673
}
1674+
ApplyTypeLookup::Generator(id) => {
1675+
(chalk_ir::TypeName::Generator(id), env.generator_kind(id))
1676+
}
16921677
ApplyTypeLookup::Closure(id) => {
16931678
(chalk_ir::TypeName::Closure(id), env.closure_kind(id))
16941679
}

chalk-ir/src/cast.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,15 @@ where
310310
}
311311
}
312312

313+
impl<I> CastTo<TypeName<I>> for GeneratorId<I>
314+
where
315+
I: Interner,
316+
{
317+
fn cast_to(self, _interner: &I) -> TypeName<I> {
318+
TypeName::Generator(self)
319+
}
320+
}
321+
313322
impl<I> CastTo<TypeName<I>> for FnDefId<I>
314323
where
315324
I: Interner,

chalk-parse/src/ast.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ pub struct StructDefn {
4444
pub struct GeneratorDefn {
4545
pub name: Identifier,
4646
pub variable_kinds: Vec<VariableKind>,
47+
pub upvars: Vec<Ty>,
4748
pub resume_ty: Ty,
4849
pub yield_ty: Ty,
4950
pub return_ty: Ty,

chalk-parse/src/parser.lalrpop

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ GeneratorDefn: GeneratorDefn = {
108108
"}" => GeneratorDefn {
109109
name: n,
110110
variable_kinds: p,
111+
upvars: upvars,
111112
witness_lifetimes: l.unwrap_or_default(),
112113
resume_ty: resume,
113114
yield_ty: yield_ty,

chalk-solve/src/clauses.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,55 @@ pub fn push_auto_trait_impls_opaque<I: Interner>(
163163
});
164164
}
165165

166+
#[instrument(level = "debug", skip(builder))]
167+
pub fn push_auto_trait_impls_generator<I: Interner>(
168+
builder: &mut ClauseBuilder<'_, I>,
169+
auto_trait_id: TraitId<I>,
170+
generator_id: GeneratorId<I>,
171+
) {
172+
let generator_datum = builder.db.generator_datum(generator_id);
173+
let interner = builder.interner();
174+
175+
// Must be an auto trait.
176+
assert!(builder.db.trait_datum(auto_trait_id).is_auto_trait());
177+
178+
// Auto traits never have generic parameters of their own (apart from `Self`).
179+
assert_eq!(
180+
builder.db.trait_datum(auto_trait_id).binders.len(interner),
181+
1
182+
);
183+
184+
builder.push_binders(&generator_datum.input_output, |builder, input_output| {
185+
let self_ty: Ty<_> = ApplicationTy {
186+
name: generator_id.cast(interner),
187+
substitution: builder.substitution_in_scope(),
188+
}
189+
.intern(interner);
190+
191+
// trait_ref = `Generator<...>: MyAutoTrait`
192+
let auto_trait_ref = TraitRef {
193+
trait_id: auto_trait_id,
194+
substitution: Substitution::from1(interner, self_ty),
195+
};
196+
197+
debug!("input output: {:?}", generator_datum.input_output);
198+
199+
// forall<P0..Pn> { // generic parameters from struct
200+
// MyStruct<...>: MyAutoTrait :-
201+
// Field0: MyAutoTrait,
202+
// ...
203+
// FieldN: MyAutoTrait
204+
// }
205+
builder.push_clause(
206+
auto_trait_ref,
207+
input_output.upvars.iter().map(|upvar_ty| TraitRef {
208+
trait_id: auto_trait_id,
209+
substitution: Substitution::from1(interner, upvar_ty.clone()),
210+
}),
211+
);
212+
});
213+
}
214+
166215
/// Given some goal `goal` that must be proven, along with
167216
/// its `environment`, figures out the program clauses that apply
168217
/// to this goal from the Rust program. So for example if the goal
@@ -249,6 +298,9 @@ fn program_clauses_that_could_match<I: Interner>(
249298
TypeName::Adt(adt_id) => {
250299
push_auto_trait_impls(builder, trait_id, *adt_id);
251300
}
301+
TypeName::Generator(generator_id) => {
302+
push_auto_trait_impls_generator(builder, trait_id, *generator_id);
303+
}
252304
_ => {}
253305
},
254306
TyData::InferenceVar(_, _) | TyData::BoundVar(_) => {

chalk-solve/src/rust_ir.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,7 @@ pub struct GeneratorInputOutputDatum<I: Interner> {
645645
pub resume_type: Ty<I>,
646646
pub yield_type: Ty<I>,
647647
pub return_type: Ty<I>,
648+
pub upvars: Vec<Ty<I>>,
648649
}
649650

650651
#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, HasInterner)]

tests/test/generators.rs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,21 @@ use super::*;
44
fn generator_is_well_formed() {
55
test! {
66
program {
7+
#[auto] trait Send { }
8+
9+
struct StructOne {}
10+
struct NotSend {}
11+
impl !Send for NotSend {}
12+
struct StructThree<'a> { val: &'a () }
13+
714
generator foo<>[resume = (), yield = ()] {
815
upvars []
916
witnesses []
1017
}
1118

1219
generator bar<T>[resume = (), yield = ()] {
13-
upvars [T; u8; i32]
14-
witnesses for<'a> [&'a u8]
20+
upvars [T; StructOne]
21+
witnesses for<'a> [NotSend]
1522
}
1623
}
1724

@@ -20,5 +27,29 @@ fn generator_is_well_formed() {
2027
} yields {
2128
"Unique"
2229
}
30+
31+
goal {
32+
foo: Send
33+
} yields {
34+
"Unique"
35+
}
36+
37+
goal {
38+
forall<T> {
39+
bar<T>: Send
40+
}
41+
} yields {
42+
"No possible solution"
43+
}
44+
45+
goal {
46+
forall<T> {
47+
if (T: Send) {
48+
bar<T>: Send
49+
}
50+
}
51+
} yields {
52+
"Unique"
53+
}
2354
}
2455
}

0 commit comments

Comments
 (0)