Skip to content

Commit

Permalink
Auto merge of #798 - lowr:feat/fn-ptr-trait, r=compiler-errors
Browse files Browse the repository at this point in the history
Support `FnPtr` trait

This PR implements support for `FnPtr` trait added by rust-lang/rust#108080. Since that PR also changed some trait impls for function pointer types in core to make use of `FnPtr`, rust-analyzer needs this to adapt to them.

Unlike other built-in traits, I didn't add a new mod specifically for `FnPtr`, because we only need to check if the type is a `TyKind::Function` and nothing else.
  • Loading branch information
bors committed Jun 24, 2023
2 parents e856e21 + fa049a6 commit 9318f7f
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 3 deletions.
1 change: 1 addition & 0 deletions chalk-integration/src/lowering.rs
Expand Up @@ -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,
}
}
}
Expand Down
1 change: 1 addition & 0 deletions chalk-parse/src/ast.rs
Expand Up @@ -163,6 +163,7 @@ pub enum WellKnownTrait {
DispatchFromDyn,
Tuple,
Pointee,
FnPtr,
}

#[derive(Clone, PartialEq, Eq, Debug)]
Expand Down
1 change: 1 addition & 0 deletions chalk-parse/src/parser.lalrpop
Expand Up @@ -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 = {
Expand Down
7 changes: 6 additions & 1 deletion chalk-solve/src/clauses/builtin_traits.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -60,6 +60,11 @@ pub fn add_builtin_program_clauses<I: Interner>(
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
Expand Down
1 change: 1 addition & 0 deletions chalk-solve/src/display/items.rs
Expand Up @@ -207,6 +207,7 @@ impl<I: Interner> RenderAsRust<I> for TraitDatum<I> {
WellKnownTrait::DispatchFromDyn => "dispatch_from_dyn",
WellKnownTrait::Tuple => "tuple_trait",
WellKnownTrait::Pointee => "pointee",
WellKnownTrait::FnPtr => "fn_ptr_trait",
};
writeln!(f, "#[lang({})]", name)?;
}
Expand Down
1 change: 1 addition & 0 deletions chalk-solve/src/rust_ir.rs
Expand Up @@ -278,6 +278,7 @@ pub enum WellKnownTrait {
DispatchFromDyn,
Tuple,
Pointee,
FnPtr,
}

chalk_ir::const_visit!(WellKnownTrait);
Expand Down
3 changes: 2 additions & 1 deletion chalk-solve/src/wf.rs
Expand Up @@ -437,7 +437,8 @@ where
| WellKnownTrait::DiscriminantKind
| WellKnownTrait::Generator
| WellKnownTrait::Pointee
| WellKnownTrait::Tuple => false,
| WellKnownTrait::Tuple
| WellKnownTrait::FnPtr => false,
};

if is_legal {
Expand Down
72 changes: 71 additions & 1 deletion tests/test/functions.rs
Expand Up @@ -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
Expand Down Expand Up @@ -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<T, U> {
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> {
T: FnPtr
}
} yields {
expect![[r#"Ambiguous; no inference guidance"#]]
}
}
}

0 comments on commit 9318f7f

Please sign in to comment.