diff --git a/book/src/clauses/well_known_traits.md b/book/src/clauses/well_known_traits.md index 203905c8723..1730e66b906 100644 --- a/book/src/clauses/well_known_traits.md +++ b/book/src/clauses/well_known_traits.md @@ -36,8 +36,9 @@ Some common examples of auto traits are `Send` and `Sync`. | trait objects | ⚬ | ⚬ | ⚬ | ✅ | ⚬ | ⚬ | ⚬ | ⚬ | ⚬ | | functions ptrs | ✅ | ✅ | ✅ | ⚬ | ⚬ | ❌ | ⚬ | ⚬ | ❌ | | raw ptrs | ✅ | ✅ | ✅ | ⚬ | ⚬ | ⚬ | ⚬ | ⚬ | ❌ | +| references | ✅ | ✅ | ✅ | ⚬ | ⚬ | ⚬ | ⚬ | ⚬ | ❌ | +| slices | ⚬ | ⚬ | ⚬ | ✅ | ⚬ | ⚬ | ⚬ | ⚬ | ❌ | | arrays❌ | ❌ | ❌ | ❌ | ❌ | ⚬ | ⚬ | ⚬ | ⚬ | ❌ | -| slices❌ | ❌ | ❌ | ⚬ | ❌ | ⚬ | ⚬ | ⚬ | ⚬ | ❌ | | closures❌ | ❌ | ❌ | ❌ | ⚬ | ⚬ | ❌ | ⚬ | ⚬ | ❌ | | generators❌ | ⚬ | ⚬ | ❌ | ⚬ | ⚬ | ⚬ | ❌ | ❌ | ❌ | | gen. witness❌ | ⚬ | ⚬ | ⚬ | ⚬ | ⚬ | ⚬ | ⚬ | ⚬ | ❌ | diff --git a/chalk-integration/src/lowering.rs b/chalk-integration/src/lowering.rs index 5272d449e94..c0680a68b14 100644 --- a/chalk-integration/src/lowering.rs +++ b/chalk-integration/src/lowering.rs @@ -1211,6 +1211,15 @@ impl LowerTy for Ty { }) .intern(interner)), + Ty::Slice { ty } => Ok(chalk_ir::TyData::Apply(chalk_ir::ApplicationTy { + name: chalk_ir::TypeName::Slice, + substitution: chalk_ir::Substitution::from_fallible( + interner, + std::iter::once(ty.lower(env)), + )?, + }) + .intern(interner)), + Ty::Raw { mutability, ty } => Ok(chalk_ir::TyData::Apply(chalk_ir::ApplicationTy { name: chalk_ir::TypeName::Raw(ast_mutability_to_chalk_mutability( mutability.clone(), diff --git a/chalk-ir/src/debug.rs b/chalk-ir/src/debug.rs index ed9b29c974b..302a1881226 100644 --- a/chalk-ir/src/debug.rs +++ b/chalk-ir/src/debug.rs @@ -144,6 +144,7 @@ impl Debug for TypeName { TypeName::Scalar(scalar) => write!(fmt, "{:?}", scalar), TypeName::Tuple(arity) => write!(fmt, "{:?}", arity), TypeName::OpaqueType(opaque_ty) => write!(fmt, "!{:?}", opaque_ty), + TypeName::Slice => write!(fmt, "{{slice}}"), TypeName::Raw(mutability) => write!(fmt, "{:?}", mutability), TypeName::Ref(mutability) => write!(fmt, "{:?}", mutability), TypeName::Error => write!(fmt, "{{error}}"), diff --git a/chalk-ir/src/lib.rs b/chalk-ir/src/lib.rs index 5b8dbc256c6..8008fac6ddd 100644 --- a/chalk-ir/src/lib.rs +++ b/chalk-ir/src/lib.rs @@ -156,6 +156,9 @@ pub enum TypeName { /// a tuple of the given arity Tuple(usize), + /// a slice type like `[T]` + Slice, + /// a raw pointer type like `*const T` or `*mut T` Raw(Mutability), diff --git a/chalk-parse/src/ast.rs b/chalk-parse/src/ast.rs index 8dad563545e..f4a81078965 100644 --- a/chalk-parse/src/ast.rs +++ b/chalk-parse/src/ast.rs @@ -193,6 +193,9 @@ pub enum Ty { Scalar { ty: ScalarType, }, + Slice { + ty: Box, + }, Raw { mutability: Mutability, ty: Box, diff --git a/chalk-parse/src/parser.lalrpop b/chalk-parse/src/parser.lalrpop index 25ede469b52..c856eea8f2f 100644 --- a/chalk-parse/src/parser.lalrpop +++ b/chalk-parse/src/parser.lalrpop @@ -208,6 +208,7 @@ TyWithoutFor: Ty = { "*" => Ty::Raw{ mutability: m, ty: Box::new(t) }, "&" "mut" => Ty::Ref{ mutability: Mutability::Mut, lifetime: l, ty: Box::new(t) }, "&" => Ty::Ref{ mutability: Mutability::Not, lifetime: l, ty: Box::new(t) }, + "[" "]" => Ty::Slice { ty: Box::new(t) }, }; ScalarType: ScalarType = { diff --git a/chalk-solve/src/clauses.rs b/chalk-solve/src/clauses.rs index 44fb2d00eee..f0bd92d0056 100644 --- a/chalk-solve/src/clauses.rs +++ b/chalk-solve/src/clauses.rs @@ -410,6 +410,7 @@ fn match_type_name( TypeName::Tuple(_) => { builder.push_fact(WellFormed::Ty(application.clone().intern(interner))) } + TypeName::Slice => builder.push_fact(WellFormed::Ty(application.clone().intern(interner))), TypeName::Raw(_) => builder.push_fact(WellFormed::Ty(application.clone().intern(interner))), TypeName::Ref(_) => builder.push_fact(WellFormed::Ty(application.clone().intern(interner))), } diff --git a/tests/lowering/mod.rs b/tests/lowering/mod.rs index 89021cfeca5..5d49e02bff5 100644 --- a/tests/lowering/mod.rs +++ b/tests/lowering/mod.rs @@ -533,3 +533,29 @@ fn refs() { } } } + +#[test] +fn slices() { + lowering_success! { + program { + trait Foo { } + + impl Foo for [i32] { } + impl Foo for [T] { } + + impl Foo for [[i32]] { } + impl Foo for [()] { } + } + } + + lowering_error! { + program { + trait Foo { } + impl Foo for [] {} + } + + error_msg { + "parse error: UnrecognizedToken { token: (29, Token(30, \"]\"), 30), expected: [\"\\\"&\\\"\", \"\\\"(\\\"\", \"\\\"*\\\"\", \"\\\"<\\\"\", \"\\\"[\\\"\", \"\\\"bool\\\"\", \"\\\"char\\\"\", \"\\\"dyn\\\"\", \"\\\"f32\\\"\", \"\\\"f64\\\"\", \"\\\"fn\\\"\", \"\\\"for\\\"\", \"\\\"i128\\\"\", \"\\\"i16\\\"\", \"\\\"i32\\\"\", \"\\\"i64\\\"\", \"\\\"i8\\\"\", \"\\\"isize\\\"\", \"\\\"u128\\\"\", \"\\\"u16\\\"\", \"\\\"u32\\\"\", \"\\\"u64\\\"\", \"\\\"u8\\\"\", \"\\\"usize\\\"\", \"r#\\\"([A-Za-z]|_)([A-Za-z0-9]|_)*\\\"#\"] }" + } + } +} diff --git a/tests/test/mod.rs b/tests/test/mod.rs index e502f20235e..108f8155b2d 100644 --- a/tests/test/mod.rs +++ b/tests/test/mod.rs @@ -316,6 +316,7 @@ mod negation; mod projection; mod refs; mod scalars; +mod slices; mod tuples; mod unify; mod wf_goals; diff --git a/tests/test/slices.rs b/tests/test/slices.rs new file mode 100644 index 00000000000..89ea71dcf64 --- /dev/null +++ b/tests/test/slices.rs @@ -0,0 +1,63 @@ +use super::*; + +#[test] +fn slices_are_not_sized() { + test! { + program { + #[lang(sized)] + trait Sized { } + } + + goal { + forall { not { [T]: Sized } } + } yields { + "Unique; substitution [], lifetime constraints []" + } + } +} + +#[test] +fn slices_are_well_formed() { + test! { + program { + } + + goal { + forall { WellFormed([T]) } + } yields { + "Unique; substitution [], lifetime constraints []" + } + } +} + +#[test] +fn slices_are_not_copy() { + test! { + program { + #[lang(copy)] + trait Copy { } + } + + goal { + forall { not { [T]: Copy } } + } yields { + "Unique; substitution [], lifetime constraints []" + } + } +} + +#[test] +fn slices_are_not_clone() { + test! { + program { + #[lang(clone)] + trait Clone { } + } + + goal { + forall { not { [T]: Clone } } + } yields { + "Unique; substitution [], lifetime constraints []" + } + } +}