Skip to content

Commit 1bddc72

Browse files
authored
Merge pull request #467 from nathanwhit/typename-array
Add array types to `TypeName`
2 parents 80c17b8 + 2534440 commit 1bddc72

File tree

12 files changed

+297
-14
lines changed

12 files changed

+297
-14
lines changed

book/src/clauses/well_known_traits.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Some common examples of auto traits are `Send` and `Sync`.
4141
| immutable refs | 📚 | 📚 ||||||||
4242
| mutable refs ||||||||||
4343
| slices ||||||||||
44-
| arrays | | | | ||||||
44+
| arrays | | | | ||||||
4545
| closures❌ ||||||||||
4646
| generators❌ ||||||||||
4747
| gen. witness❌ ||||||||||

chalk-integration/src/lowering.rs

+43-8
Original file line numberDiff line numberDiff line change
@@ -1394,6 +1394,18 @@ impl LowerTy for Ty {
13941394
})
13951395
.intern(interner)),
13961396

1397+
Ty::Array { ty, len } => Ok(chalk_ir::TyData::Apply(chalk_ir::ApplicationTy {
1398+
name: chalk_ir::TypeName::Array,
1399+
substitution: chalk_ir::Substitution::from(
1400+
interner,
1401+
&[
1402+
ty.lower(env)?.cast(interner),
1403+
len.lower(env)?.cast(interner),
1404+
],
1405+
),
1406+
})
1407+
.intern(interner)),
1408+
13971409
Ty::Slice { ty } => Ok(chalk_ir::TyData::Apply(chalk_ir::ApplicationTy {
13981410
name: chalk_ir::TypeName::Slice,
13991411
substitution: chalk_ir::Substitution::from_fallible(
@@ -1447,6 +1459,36 @@ impl LowerTy for Ty {
14471459
}
14481460
}
14491461

1462+
trait LowerConst {
1463+
fn lower(&self, env: &Env) -> LowerResult<chalk_ir::Const<ChalkIr>>;
1464+
}
1465+
1466+
impl LowerConst for Const {
1467+
fn lower(&self, env: &Env) -> LowerResult<chalk_ir::Const<ChalkIr>> {
1468+
let interner = env.interner();
1469+
match self {
1470+
Const::Id(name) => {
1471+
let parameter = env.lookup_generic_arg(name)?;
1472+
parameter
1473+
.constant(interner)
1474+
.ok_or_else(|| RustIrError::IncorrectParameterKind {
1475+
identifier: name.clone(),
1476+
expected: Kind::Const,
1477+
actual: parameter.kind(),
1478+
})
1479+
.map(|c| c.clone())
1480+
}
1481+
Const::Value(value) => Ok(chalk_ir::ConstData {
1482+
ty: get_type_of_u32(),
1483+
value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst {
1484+
interned: value.clone(),
1485+
}),
1486+
}
1487+
.intern(interner)),
1488+
}
1489+
}
1490+
}
1491+
14501492
trait LowerGenericArg {
14511493
fn lower(&self, env: &Env) -> LowerResult<chalk_ir::GenericArg<ChalkIr>>;
14521494
}
@@ -1458,14 +1500,7 @@ impl LowerGenericArg for GenericArg {
14581500
GenericArg::Ty(ref t) => Ok(t.lower(env)?.cast(interner)),
14591501
GenericArg::Lifetime(ref l) => Ok(l.lower(env)?.cast(interner)),
14601502
GenericArg::Id(name) => env.lookup_generic_arg(&name),
1461-
GenericArg::ConstValue(value) => Ok(chalk_ir::ConstData {
1462-
ty: get_type_of_u32(),
1463-
value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst {
1464-
interned: value.clone(),
1465-
}),
1466-
}
1467-
.intern(interner)
1468-
.cast(interner)),
1503+
GenericArg::Const(c) => Ok(c.lower(env)?.cast(interner)),
14691504
}
14701505
}
14711506
}

chalk-ir/src/debug.rs

+1
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ impl<I: Interner> Debug for TypeName<I> {
168168
TypeName::Raw(mutability) => write!(fmt, "{:?}", mutability),
169169
TypeName::Ref(mutability) => write!(fmt, "{:?}", mutability),
170170
TypeName::Never => write!(fmt, "Never"),
171+
TypeName::Array => write!(fmt, "{{array}}"),
171172
TypeName::Error => write!(fmt, "{{error}}"),
172173
}
173174
}

chalk-ir/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ pub enum TypeName<I: Interner> {
157157
/// a tuple of the given arity
158158
Tuple(usize),
159159

160+
/// an array type like `[T; N]`
161+
Array,
162+
160163
/// a slice type like `[T]`
161164
Slice,
162165

chalk-parse/src/ast.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,13 @@ pub enum GenericArg {
109109
Ty(Ty),
110110
Lifetime(Lifetime),
111111
Id(Identifier),
112-
ConstValue(u32),
112+
Const(Const),
113+
}
114+
115+
#[derive(Clone, PartialEq, Eq, Debug)]
116+
pub enum Const {
117+
Id(Identifier),
118+
Value(u32),
113119
}
114120

115121
#[derive(Clone, PartialEq, Eq, Debug)]
@@ -212,6 +218,10 @@ pub enum Ty {
212218
Slice {
213219
ty: Box<Ty>,
214220
},
221+
Array {
222+
ty: Box<Ty>,
223+
len: Const,
224+
},
215225
Raw {
216226
mutability: Mutability,
217227
ty: Box<Ty>,

chalk-parse/src/parser.lalrpop

+11-1
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ TyWithoutId: Ty = {
239239
"&" <l: Lifetime> "mut" <t:Ty> => Ty::Ref{ mutability: Mutability::Mut, lifetime: l, ty: Box::new(t) },
240240
"&" <l: Lifetime> <t:Ty> => Ty::Ref{ mutability: Mutability::Not, lifetime: l, ty: Box::new(t) },
241241
"[" <t:Ty> "]" => Ty::Slice { ty: Box::new(t) },
242+
"[" <t:Ty> ";" <len:Const> "]" => Ty::Array { ty: Box::new(t), len },
242243
};
243244

244245
ScalarType: ScalarType = {
@@ -280,11 +281,20 @@ Lifetime: Lifetime = {
280281
<n:LifetimeId> => Lifetime::Id { name: n },
281282
};
282283

284+
ConstWithoutId: Const = {
285+
ConstValue => Const::Value(<>),
286+
};
287+
288+
Const : Const = {
289+
Id => Const::Id(<>),
290+
ConstWithoutId,
291+
};
292+
283293
GenericArg: GenericArg = {
284294
TyWithoutId => GenericArg::Ty(<>),
285295
Lifetime => GenericArg::Lifetime(<>),
286296
Id => GenericArg::Id(<>),
287-
ConstValue => GenericArg::ConstValue(<>),
297+
ConstWithoutId => GenericArg::Const(<>),
288298
};
289299

290300
ProjectionTy: ProjectionTy = {

chalk-solve/src/clauses.rs

+1
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ fn match_type_name<I: Interner>(
421421
| TypeName::Slice
422422
| TypeName::Raw(_)
423423
| TypeName::Ref(_)
424+
| TypeName::Array
424425
| TypeName::Never => {
425426
builder.push_fact(WellFormed::Ty(application.clone().intern(interner)))
426427
}

chalk-solve/src/clauses/builtin_traits/copy.rs

+10
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::clauses::builtin_traits::needs_impl_for_tys;
22
use crate::clauses::ClauseBuilder;
33
use crate::{Interner, RustIrDatabase, TraitRef};
44
use chalk_ir::{ApplicationTy, Substitution, TyData, TypeName};
5+
use std::iter;
56

67
fn push_tuple_copy_conditions<I: Interner>(
78
db: &dyn RustIrDatabase<I>,
@@ -41,6 +42,15 @@ pub fn add_copy_program_clauses<I: Interner>(
4142
TypeName::Tuple(arity) => {
4243
push_tuple_copy_conditions(db, builder, trait_ref, *arity, substitution)
4344
}
45+
TypeName::Array => {
46+
let interner = db.interner();
47+
needs_impl_for_tys(
48+
db,
49+
builder,
50+
trait_ref,
51+
iter::once(substitution.at(interner, 0).assert_ty_ref(interner).clone()),
52+
);
53+
}
4454
_ => return,
4555
},
4656
TyData::Function(_) => builder.push_fact(trait_ref.clone()),

chalk-solve/src/clauses/builtin_traits/sized.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,11 @@ pub fn add_sized_program_clauses<I: Interner>(
7474
TypeName::Tuple(arity) => {
7575
push_tuple_sized_conditions(db, builder, trait_ref, *arity, substitution)
7676
}
77-
TypeName::Never | TypeName::Scalar(_) | TypeName::Raw(_) | TypeName::Ref(_) => {
78-
builder.push_fact(trait_ref.clone())
79-
}
77+
TypeName::Array
78+
| TypeName::Never
79+
| TypeName::Scalar(_)
80+
| TypeName::Raw(_)
81+
| TypeName::Ref(_) => builder.push_fact(trait_ref.clone()),
8082
_ => return,
8183
},
8284
TyData::Function(_) => builder.push_fact(trait_ref.clone()),

tests/lowering/mod.rs

+93
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,52 @@ fn check_variable_kinds() {
288288
"incorrect parameter kind for trait `IntoTime`: expected lifetime, found type"
289289
}
290290
}
291+
292+
lowering_error! {
293+
program {
294+
trait Length<const N> {}
295+
struct Foo {}
296+
impl<T> Length<T> for Foo {}
297+
}
298+
error_msg {
299+
"incorrect parameter kind for trait `Length`: expected const, found type"
300+
}
301+
}
302+
303+
lowering_error! {
304+
program {
305+
trait Length<const N> {}
306+
struct Foo {}
307+
impl<'a> Length<'a> for Foo {}
308+
}
309+
error_msg {
310+
"incorrect parameter kind for trait `Length`: expected const, found lifetime"
311+
}
312+
}
313+
314+
lowering_error! {
315+
program {
316+
trait Into<T> {}
317+
struct Foo {}
318+
impl<const N> Into<N> for Foo {}
319+
}
320+
321+
error_msg {
322+
"incorrect parameter kind for trait `Into`: expected type, found const"
323+
}
324+
}
325+
326+
lowering_error! {
327+
program {
328+
trait IntoTime<'a> {}
329+
struct Foo {}
330+
impl<const N> IntoTime<N> for Foo {}
331+
}
332+
333+
error_msg {
334+
"incorrect parameter kind for trait `IntoTime`: expected lifetime, found const"
335+
}
336+
}
291337
}
292338

293339
#[test]
@@ -584,3 +630,50 @@ fn fn_defs() {
584630
}
585631
}
586632
}
633+
#[test]
634+
fn arrays() {
635+
lowering_success! {
636+
program {
637+
struct Baz { }
638+
fn foo(bar: [Baz; 3]);
639+
640+
fn bar<const N>(baz: [Baz; N]);
641+
}
642+
}
643+
644+
lowering_error! {
645+
program {
646+
struct Baz { }
647+
648+
fn foo<T>(baz: [Baz; u32]);
649+
}
650+
651+
error_msg {
652+
"parse error: UnrecognizedToken"
653+
}
654+
}
655+
656+
lowering_error! {
657+
program {
658+
struct Baz { }
659+
660+
fn foo<T>(baz: [Baz; T]);
661+
}
662+
663+
error_msg {
664+
"incorrect parameter kind for `T`: expected const, found type"
665+
}
666+
}
667+
668+
lowering_error! {
669+
program {
670+
struct Baz { }
671+
672+
fn foo<'a>(baz: [Baz; 'a]);
673+
}
674+
675+
error_msg {
676+
"parse error: UnrecognizedToken"
677+
}
678+
}
679+
}

0 commit comments

Comments
 (0)