Skip to content

Commit f9f89c5

Browse files
Implement support for Tuple trait
1 parent cadaba9 commit f9f89c5

File tree

9 files changed

+94
-1
lines changed

9 files changed

+94
-1
lines changed

chalk-integration/src/lowering.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1143,6 +1143,7 @@ impl Lower for WellKnownTrait {
11431143
WellKnownTrait::DiscriminantKind => rust_ir::WellKnownTrait::DiscriminantKind,
11441144
WellKnownTrait::Generator => rust_ir::WellKnownTrait::Generator,
11451145
WellKnownTrait::DispatchFromDyn => rust_ir::WellKnownTrait::DispatchFromDyn,
1146+
WellKnownTrait::Tuple => rust_ir::WellKnownTrait::Tuple,
11461147
}
11471148
}
11481149
}

chalk-parse/src/ast.rs

+1
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ pub enum WellKnownTrait {
161161
DiscriminantKind,
162162
Generator,
163163
DispatchFromDyn,
164+
Tuple,
164165
}
165166

166167
#[derive(Clone, PartialEq, Eq, Debug)]

chalk-parse/src/parser.lalrpop

+1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ WellKnownTrait: WellKnownTrait = {
6969
"#" "[" "lang" "(" "discriminant_kind" ")" "]" => WellKnownTrait::DiscriminantKind,
7070
"#" "[" "lang" "(" "generator" ")" "]" => WellKnownTrait::Generator,
7171
"#" "[" "lang" "(" "dispatch_from_dyn" ")" "]" => WellKnownTrait::DispatchFromDyn,
72+
"#" "[" "lang" "(" "tuple_trait" ")" "]" => WellKnownTrait::Tuple,
7273
};
7374

7475
AdtReprAttr: AdtReprAttr = {

chalk-solve/src/clauses/builtin_traits.rs

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ mod discriminant_kind;
88
mod fn_family;
99
mod generator;
1010
mod sized;
11+
mod tuple;
1112
mod unsize;
1213

1314
/// For well known traits we have special hard-coded impls, either as an
@@ -50,6 +51,9 @@ pub fn add_builtin_program_clauses<I: Interner>(
5051
WellKnownTrait::Generator => {
5152
generator::add_generator_program_clauses(db, builder, self_ty)?;
5253
}
54+
WellKnownTrait::Tuple => {
55+
tuple::add_tuple_program_clauses(db, builder, self_ty)?;
56+
}
5357
// There are no builtin impls provided for the following traits:
5458
WellKnownTrait::Unpin
5559
| WellKnownTrait::Drop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
use crate::clauses::ClauseBuilder;
2+
use crate::rust_ir::WellKnownTrait;
3+
use crate::{Interner, RustIrDatabase, TraitRef};
4+
use chalk_ir::{Floundered, Substitution, Ty, TyKind};
5+
6+
/// Add implicit impls of the generator trait, i.e., add a clause that all generators implement
7+
/// `Generator` and clauses for `Generator`'s associated types.
8+
pub fn add_tuple_program_clauses<I: Interner>(
9+
db: &dyn RustIrDatabase<I>,
10+
builder: &mut ClauseBuilder<'_, I>,
11+
self_ty: Ty<I>,
12+
) -> Result<(), Floundered> {
13+
let interner = db.interner();
14+
15+
match self_ty.kind(interner) {
16+
TyKind::Tuple(..) => {
17+
let trait_id = db.well_known_trait_id(WellKnownTrait::Tuple).unwrap();
18+
19+
builder.push_fact(TraitRef {
20+
trait_id,
21+
substitution: Substitution::from1(interner, self_ty),
22+
});
23+
24+
Ok(())
25+
}
26+
27+
// Generator trait is non-enumerable
28+
TyKind::InferenceVar(..) | TyKind::BoundVar(_) | TyKind::Alias(..) => Err(Floundered),
29+
_ => Ok(()),
30+
}
31+
}

chalk-solve/src/display/items.rs

+1
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ impl<I: Interner> RenderAsRust<I> for TraitDatum<I> {
205205
WellKnownTrait::DiscriminantKind => "discriminant_kind",
206206
WellKnownTrait::Generator => "generator",
207207
WellKnownTrait::DispatchFromDyn => "dispatch_from_dyn",
208+
WellKnownTrait::Tuple => "tuple_trait",
208209
};
209210
writeln!(f, "#[lang({})]", name)?;
210211
}

chalk-solve/src/rust_ir.rs

+1
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ pub enum WellKnownTrait {
277277
DiscriminantKind,
278278
Generator,
279279
DispatchFromDyn,
280+
Tuple,
280281
}
281282

282283
chalk_ir::const_visit!(WellKnownTrait);

chalk-solve/src/wf.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,8 @@ where
435435
| WellKnownTrait::Unsize
436436
| WellKnownTrait::Sized
437437
| WellKnownTrait::DiscriminantKind
438-
| WellKnownTrait::Generator => false,
438+
| WellKnownTrait::Generator
439+
| WellKnownTrait::Tuple => false,
439440
};
440441

441442
if is_legal {

tests/test/tuples.rs

+52
Original file line numberDiff line numberDiff line change
@@ -294,3 +294,55 @@ fn tuples_are_wf() {
294294
}
295295
}
296296
}
297+
298+
#[test]
299+
fn tuples_implement_tuple_trait() {
300+
test! {
301+
program {
302+
#[lang(tuple_trait)]
303+
trait Tuple { }
304+
}
305+
306+
goal {
307+
(): Tuple
308+
} yields {
309+
expect![["Unique"]]
310+
}
311+
312+
goal {
313+
(u8,): Tuple
314+
} yields {
315+
expect![["Unique"]]
316+
}
317+
318+
goal {
319+
(i32, i32): Tuple
320+
} yields {
321+
expect![["Unique"]]
322+
}
323+
324+
goal {
325+
([u8],): Tuple
326+
} yields {
327+
expect![["Unique"]]
328+
}
329+
330+
goal {
331+
forall<T> { (T,): Tuple }
332+
} yields {
333+
expect![["Unique"]]
334+
}
335+
336+
goal {
337+
i32: Tuple
338+
} yields {
339+
expect![["No possible solution"]]
340+
}
341+
342+
goal {
343+
exists<T> { T: Tuple }
344+
} yields {
345+
expect![["Ambiguous; no inference guidance"]]
346+
}
347+
}
348+
}

0 commit comments

Comments
 (0)