From fa049a6f44423a7a425928bf220f994eef1b1973 Mon Sep 17 00:00:00 2001 From: Ryo Yoshida Date: Sun, 25 Jun 2023 01:59:33 +0900 Subject: [PATCH] Support `FnPtr` trait --- chalk-integration/src/lowering.rs | 1 + chalk-parse/src/ast.rs | 1 + chalk-parse/src/parser.lalrpop | 1 + chalk-solve/src/clauses/builtin_traits.rs | 7 ++- chalk-solve/src/display/items.rs | 1 + chalk-solve/src/rust_ir.rs | 1 + chalk-solve/src/wf.rs | 3 +- tests/test/functions.rs | 72 ++++++++++++++++++++++- 8 files changed, 84 insertions(+), 3 deletions(-) diff --git a/chalk-integration/src/lowering.rs b/chalk-integration/src/lowering.rs index 40d317a8a8e..8a2c6655428 100644 --- a/chalk-integration/src/lowering.rs +++ b/chalk-integration/src/lowering.rs @@ -1141,6 +1141,7 @@ impl Lower for WellKnownTrait { WellKnownTrait::DispatchFromDyn => rust_ir::WellKnownTrait::DispatchFromDyn, WellKnownTrait::Tuple => rust_ir::WellKnownTrait::Tuple, WellKnownTrait::Pointee => rust_ir::WellKnownTrait::Pointee, + WellKnownTrait::FnPtr => rust_ir::WellKnownTrait::FnPtr, } } } diff --git a/chalk-parse/src/ast.rs b/chalk-parse/src/ast.rs index 127952ffc88..186749659f4 100644 --- a/chalk-parse/src/ast.rs +++ b/chalk-parse/src/ast.rs @@ -163,6 +163,7 @@ pub enum WellKnownTrait { DispatchFromDyn, Tuple, Pointee, + FnPtr, } #[derive(Clone, PartialEq, Eq, Debug)] diff --git a/chalk-parse/src/parser.lalrpop b/chalk-parse/src/parser.lalrpop index c5094ef6781..b83fe8e7943 100644 --- a/chalk-parse/src/parser.lalrpop +++ b/chalk-parse/src/parser.lalrpop @@ -71,6 +71,7 @@ WellKnownTrait: WellKnownTrait = { "#" "[" "lang" "(" "dispatch_from_dyn" ")" "]" => WellKnownTrait::DispatchFromDyn, "#" "[" "lang" "(" "tuple_trait" ")" "]" => WellKnownTrait::Tuple, "#" "[" "lang" "(" "pointee_trait" ")" "]" => WellKnownTrait::Pointee, + "#" "[" "lang" "(" "fn_ptr_trait" ")" "]" => WellKnownTrait::FnPtr, }; AdtReprAttr: AdtReprAttr = { diff --git a/chalk-solve/src/clauses/builtin_traits.rs b/chalk-solve/src/clauses/builtin_traits.rs index 97cc96d090b..24119023be0 100644 --- a/chalk-solve/src/clauses/builtin_traits.rs +++ b/chalk-solve/src/clauses/builtin_traits.rs @@ -2,7 +2,7 @@ use super::{builder::ClauseBuilder, generalize}; use crate::{ rust_ir::AdtKind, CanonicalVarKinds, Interner, RustIrDatabase, TraitRef, WellKnownTrait, }; -use chalk_ir::{Floundered, Substitution, Ty}; +use chalk_ir::{Floundered, Substitution, Ty, TyKind}; mod clone; mod copy; @@ -60,6 +60,11 @@ pub fn add_builtin_program_clauses( WellKnownTrait::Pointee => { pointee::add_pointee_program_clauses(db, builder, self_ty)?; } + WellKnownTrait::FnPtr => { + if let TyKind::Function(_) = self_ty.kind(db.interner()) { + builder.push_fact(trait_ref); + } + } // There are no builtin impls provided for the following traits: WellKnownTrait::Unpin | WellKnownTrait::Drop diff --git a/chalk-solve/src/display/items.rs b/chalk-solve/src/display/items.rs index ec05277a3ce..87ecae7db89 100644 --- a/chalk-solve/src/display/items.rs +++ b/chalk-solve/src/display/items.rs @@ -207,6 +207,7 @@ impl RenderAsRust for TraitDatum { WellKnownTrait::DispatchFromDyn => "dispatch_from_dyn", WellKnownTrait::Tuple => "tuple_trait", WellKnownTrait::Pointee => "pointee", + WellKnownTrait::FnPtr => "fn_ptr_trait", }; writeln!(f, "#[lang({})]", name)?; } diff --git a/chalk-solve/src/rust_ir.rs b/chalk-solve/src/rust_ir.rs index e99e227e8fe..de0f633c449 100644 --- a/chalk-solve/src/rust_ir.rs +++ b/chalk-solve/src/rust_ir.rs @@ -278,6 +278,7 @@ pub enum WellKnownTrait { DispatchFromDyn, Tuple, Pointee, + FnPtr, } chalk_ir::const_visit!(WellKnownTrait); diff --git a/chalk-solve/src/wf.rs b/chalk-solve/src/wf.rs index 6daa2414956..57e124c9688 100644 --- a/chalk-solve/src/wf.rs +++ b/chalk-solve/src/wf.rs @@ -437,7 +437,8 @@ where | WellKnownTrait::DiscriminantKind | WellKnownTrait::Generator | WellKnownTrait::Pointee - | WellKnownTrait::Tuple => false, + | WellKnownTrait::Tuple + | WellKnownTrait::FnPtr => false, }; if is_legal { diff --git a/tests/test/functions.rs b/tests/test/functions.rs index d68693d8c7f..7105c908b9a 100644 --- a/tests/test/functions.rs +++ b/tests/test/functions.rs @@ -66,7 +66,6 @@ fn function_implement_fn_traits() { impl Clone for Ty { } opaque type MyOpaque: Clone = Ty; - } // Simple test: make sure a fully monomorphic type implements FnOnce @@ -246,3 +245,74 @@ fn function_implement_fn_traits() { } } } + +#[test] +fn functions_implement_fn_ptr_trait() { + test! { + program { + #[lang(fn_ptr_trait)] + trait FnPtr {} + + closure closure_ty(self,) {} + fn fn_def(); + } + + goal { + fn(()) -> (): FnPtr + } yields { + expect![[r#"Unique"#]] + } + + goal { + unsafe fn(): FnPtr + } yields { + expect![[r#"Unique"#]] + } + + goal { + extern "C" fn(u32, ...): FnPtr + } yields { + expect![[r#"Unique"#]] + } + + goal { + for<'a> fn(&'a ()): FnPtr + } yields { + expect![[r#"Unique"#]] + } + + goal { + forall { + fn(T) -> U: FnPtr + } + } yields { + expect![[r#"Unique"#]] + } + + goal { + i32: FnPtr + } yields { + expect![[r#"No possible solution"#]] + } + + goal { + closure_ty: FnPtr + } yields { + expect![[r#"No possible solution"#]] + } + + goal { + fn_def: FnPtr + } yields { + expect![[r#"No possible solution"#]] + } + + goal { + exists { + T: FnPtr + } + } yields { + expect![[r#"Ambiguous; no inference guidance"#]] + } + } +}