diff --git a/book/src/clauses/well_known_traits.md b/book/src/clauses/well_known_traits.md index 83fd345c099..203905c8723 100644 --- a/book/src/clauses/well_known_traits.md +++ b/book/src/clauses/well_known_traits.md @@ -35,6 +35,7 @@ Some common examples of auto traits are `Send` and `Sync`. | scalar types | πŸ“š | πŸ“š | βœ… | ⚬ | ⚬ | ⚬ | ⚬ | ⚬ | ❌ | | trait objects | ⚬ | ⚬ | ⚬ | βœ… | ⚬ | ⚬ | ⚬ | ⚬ | ⚬ | | functions ptrs | βœ… | βœ… | βœ… | ⚬ | ⚬ | ❌ | ⚬ | ⚬ | ❌ | +| raw ptrs | βœ… | βœ… | βœ… | ⚬ | ⚬ | ⚬ | ⚬ | ⚬ | ❌ | | arrays❌ | ❌ | ❌ | ❌ | ❌ | ⚬ | ⚬ | ⚬ | ⚬ | ❌ | | slices❌ | ❌ | ❌ | ⚬ | ❌ | ⚬ | ⚬ | ⚬ | ⚬ | ❌ | | closures❌ | ❌ | ❌ | ❌ | ⚬ | ⚬ | ❌ | ⚬ | ⚬ | ❌ | diff --git a/chalk-integration/src/lowering.rs b/chalk-integration/src/lowering.rs index d8dde09af2b..67a5b8a669b 100644 --- a/chalk-integration/src/lowering.rs +++ b/chalk-integration/src/lowering.rs @@ -1210,6 +1210,17 @@ impl LowerTy for Ty { substitution: chalk_ir::Substitution::empty(interner), }) .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(), + )), + substitution: chalk_ir::Substitution::from_fallible( + interner, + std::iter::once(Ok(ty.lower(env)?)), + )?, + }) + .intern(interner)), } } } @@ -1591,3 +1602,10 @@ fn ast_scalar_to_chalk_scalar(scalar: ScalarType) -> chalk_ir::Scalar { ScalarType::Char => chalk_ir::Scalar::Char, } } + +fn ast_mutability_to_chalk_mutability(mutability: Mutability) -> chalk_ir::Mutability { + match mutability { + Mutability::Mut => chalk_ir::Mutability::Mut, + Mutability::Not => chalk_ir::Mutability::Not, + } +} diff --git a/chalk-ir/src/debug.rs b/chalk-ir/src/debug.rs index f4946cd9c5d..79b99656f9d 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::Raw(mutability) => write!(fmt, "{:?}", mutability), TypeName::Error => write!(fmt, "{{error}}"), } } diff --git a/chalk-ir/src/fold/boring_impls.rs b/chalk-ir/src/fold/boring_impls.rs index 212b8db703f..b30e489ecb3 100644 --- a/chalk-ir/src/fold/boring_impls.rs +++ b/chalk-ir/src/fold/boring_impls.rs @@ -248,6 +248,7 @@ copy_fold!(IntTy); copy_fold!(FloatTy); copy_fold!(Scalar); copy_fold!(ClausePriority); +copy_fold!(Mutability); #[macro_export] macro_rules! id_fold { diff --git a/chalk-ir/src/lib.rs b/chalk-ir/src/lib.rs index 54569cd5404..dd1c96c55dd 100644 --- a/chalk-ir/src/lib.rs +++ b/chalk-ir/src/lib.rs @@ -136,6 +136,12 @@ pub enum Scalar { Float(FloatTy), } +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum Mutability { + Mut, + Not, +} + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Fold, Visit)] pub enum TypeName { /// a type like `Vec` @@ -150,6 +156,9 @@ pub enum TypeName { /// a tuple of the given arity Tuple(usize), + /// a raw pointer type like `*const T` or `*mut T` + Raw(Mutability), + /// a placeholder for opaque types like `impl Trait` OpaqueType(OpaqueTyId), diff --git a/chalk-ir/src/visit/boring_impls.rs b/chalk-ir/src/visit/boring_impls.rs index 5cb14be6912..93199584314 100644 --- a/chalk-ir/src/visit/boring_impls.rs +++ b/chalk-ir/src/visit/boring_impls.rs @@ -6,9 +6,9 @@ use crate::{ AssocTypeId, ClausePriority, DebruijnIndex, FloatTy, Goals, ImplId, IntTy, Interner, - OpaqueTyId, Parameter, ParameterKind, PlaceholderIndex, ProgramClause, ProgramClauseData, - ProgramClauses, QuantifiedWhereClauses, QuantifierKind, Scalar, StructId, Substitution, - SuperVisit, TraitId, UintTy, UniverseIndex, Visit, VisitResult, Visitor, + Mutability, OpaqueTyId, Parameter, ParameterKind, PlaceholderIndex, ProgramClause, + ProgramClauseData, ProgramClauses, QuantifiedWhereClauses, QuantifierKind, Scalar, StructId, + Substitution, SuperVisit, TraitId, UintTy, UniverseIndex, Visit, VisitResult, Visitor, }; use chalk_engine::{context::Context, ExClause, FlounderedSubgoal, Literal}; use std::{marker::PhantomData, sync::Arc}; @@ -211,6 +211,7 @@ const_visit!(Scalar); const_visit!(UintTy); const_visit!(IntTy); const_visit!(FloatTy); +const_visit!(Mutability); #[macro_export] macro_rules! id_visit { diff --git a/chalk-parse/src/ast.rs b/chalk-parse/src/ast.rs index 627270dbf00..57bd8e34827 100644 --- a/chalk-parse/src/ast.rs +++ b/chalk-parse/src/ast.rs @@ -193,6 +193,10 @@ pub enum Ty { Scalar { ty: ScalarType, }, + Raw { + mutability: Mutability, + ty: Box, + }, } #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -230,6 +234,12 @@ pub enum ScalarType { Float(FloatTy), } +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum Mutability { + Mut, + Not, +} + #[derive(Clone, PartialEq, Eq, Debug)] pub enum Lifetime { Id { name: Identifier }, diff --git a/chalk-parse/src/parser.lalrpop b/chalk-parse/src/parser.lalrpop index 72aa3cf3a84..86c8a555504 100644 --- a/chalk-parse/src/parser.lalrpop +++ b/chalk-parse/src/parser.lalrpop @@ -205,6 +205,7 @@ TyWithoutFor: Ty = { "<" > ">" => Ty::Apply { name: n, args: a }, => Ty::Projection { proj: p }, "(" ")" => t, + "*" => Ty::Raw{ mutability: m, ty: Box::new(t) }, }; ScalarType: ScalarType = { @@ -237,6 +238,11 @@ TupleOrParensInner: Ty = { () => Ty::Tuple { types: vec![] }, }; +Mutability: Mutability = { + "mut" => Mutability::Mut, + "const" => Mutability::Not, +}; + Lifetime: Lifetime = { => Lifetime::Id { name: n }, }; diff --git a/chalk-solve/src/clauses.rs b/chalk-solve/src/clauses.rs index c87f430757c..24e076d7025 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::Raw(_) => builder.push_fact(WellFormed::Ty(application.clone().intern(interner))), } } diff --git a/chalk-solve/src/clauses/builtin_traits/copy.rs b/chalk-solve/src/clauses/builtin_traits/copy.rs index dd3dc742280..f6b4627315c 100644 --- a/chalk-solve/src/clauses/builtin_traits/copy.rs +++ b/chalk-solve/src/clauses/builtin_traits/copy.rs @@ -41,6 +41,7 @@ pub fn add_copy_program_clauses( TypeName::Tuple(arity) => { push_tuple_copy_conditions(db, builder, trait_ref, *arity, substitution) } + TypeName::Raw(_) => builder.push_fact(trait_ref.clone()), _ => return, }, TyData::Function(_) => builder.push_fact(trait_ref.clone()), diff --git a/chalk-solve/src/clauses/builtin_traits/sized.rs b/chalk-solve/src/clauses/builtin_traits/sized.rs index add2d9bfdfe..f9f57e15f3a 100644 --- a/chalk-solve/src/clauses/builtin_traits/sized.rs +++ b/chalk-solve/src/clauses/builtin_traits/sized.rs @@ -75,6 +75,7 @@ pub fn add_sized_program_clauses( TypeName::Tuple(arity) => { push_tuple_sized_conditions(db, builder, trait_ref, *arity, substitution) } + TypeName::Raw(_) => builder.push_fact(trait_ref.clone()), _ => return, }, TyData::Function(_) => builder.push_fact(trait_ref.clone()), diff --git a/tests/lowering/mod.rs b/tests/lowering/mod.rs index 10e17c38a39..8c9cb0aabc8 100644 --- a/tests/lowering/mod.rs +++ b/tests/lowering/mod.rs @@ -471,7 +471,41 @@ fn scalars() { } error_msg { - "parse error: UnrecognizedToken { token: (8, Token(49, \"i32\"), 11), expected: [\"r#\\\"([A-Za-z]|_)([A-Za-z0-9]|_)*\\\"#\"] }" + "parse error: UnrecognizedToken { token: (8, Token(51, \"i32\"), 11), expected: [\"r#\\\"([A-Za-z]|_)([A-Za-z0-9]|_)*\\\"#\"] }" + } + } +} + +#[test] +fn raw_pointers() { + lowering_success! { + program { + trait Quux { } + struct Foo { a: *const T } + + struct Bar { a: *mut T } + + impl Quux for Foo<*mut T> { } + impl Quux for Bar<*const T> { } + } + } + + lowering_error! { + program { + struct *const i32 { } + } + error_msg { + "parse error: UnrecognizedToken { token: (8, Token(7, \"*\"), 9), expected: [\"r#\\\"([A-Za-z]|_)([A-Za-z0-9]|_)*\\\"#\"] }" + } + } + + lowering_error! { + program { + trait Foo { } + impl Foo for *i32 { } + } + error_msg { + "parse error: UnrecognizedToken { token: (30, Token(51, \"i32\"), 33), expected: [\"\\\"const\\\"\", \"\\\"mut\\\"\"] }" } } }