Skip to content

Commit 9318f7f

Browse files
committed
Auto merge of #798 - lowr:feat/fn-ptr-trait, r=compiler-errors
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.
2 parents e856e21 + fa049a6 commit 9318f7f

File tree

8 files changed

+84
-3
lines changed

8 files changed

+84
-3
lines changed

chalk-integration/src/lowering.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,7 @@ impl Lower for WellKnownTrait {
11411141
WellKnownTrait::DispatchFromDyn => rust_ir::WellKnownTrait::DispatchFromDyn,
11421142
WellKnownTrait::Tuple => rust_ir::WellKnownTrait::Tuple,
11431143
WellKnownTrait::Pointee => rust_ir::WellKnownTrait::Pointee,
1144+
WellKnownTrait::FnPtr => rust_ir::WellKnownTrait::FnPtr,
11441145
}
11451146
}
11461147
}

chalk-parse/src/ast.rs

+1
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ pub enum WellKnownTrait {
163163
DispatchFromDyn,
164164
Tuple,
165165
Pointee,
166+
FnPtr,
166167
}
167168

168169
#[derive(Clone, PartialEq, Eq, Debug)]

chalk-parse/src/parser.lalrpop

+1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ WellKnownTrait: WellKnownTrait = {
7171
"#" "[" "lang" "(" "dispatch_from_dyn" ")" "]" => WellKnownTrait::DispatchFromDyn,
7272
"#" "[" "lang" "(" "tuple_trait" ")" "]" => WellKnownTrait::Tuple,
7373
"#" "[" "lang" "(" "pointee_trait" ")" "]" => WellKnownTrait::Pointee,
74+
"#" "[" "lang" "(" "fn_ptr_trait" ")" "]" => WellKnownTrait::FnPtr,
7475
};
7576

7677
AdtReprAttr: AdtReprAttr = {

chalk-solve/src/clauses/builtin_traits.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::{builder::ClauseBuilder, generalize};
22
use crate::{
33
rust_ir::AdtKind, CanonicalVarKinds, Interner, RustIrDatabase, TraitRef, WellKnownTrait,
44
};
5-
use chalk_ir::{Floundered, Substitution, Ty};
5+
use chalk_ir::{Floundered, Substitution, Ty, TyKind};
66

77
mod clone;
88
mod copy;
@@ -60,6 +60,11 @@ pub fn add_builtin_program_clauses<I: Interner>(
6060
WellKnownTrait::Pointee => {
6161
pointee::add_pointee_program_clauses(db, builder, self_ty)?;
6262
}
63+
WellKnownTrait::FnPtr => {
64+
if let TyKind::Function(_) = self_ty.kind(db.interner()) {
65+
builder.push_fact(trait_ref);
66+
}
67+
}
6368
// There are no builtin impls provided for the following traits:
6469
WellKnownTrait::Unpin
6570
| WellKnownTrait::Drop

chalk-solve/src/display/items.rs

+1
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ impl<I: Interner> RenderAsRust<I> for TraitDatum<I> {
207207
WellKnownTrait::DispatchFromDyn => "dispatch_from_dyn",
208208
WellKnownTrait::Tuple => "tuple_trait",
209209
WellKnownTrait::Pointee => "pointee",
210+
WellKnownTrait::FnPtr => "fn_ptr_trait",
210211
};
211212
writeln!(f, "#[lang({})]", name)?;
212213
}

chalk-solve/src/rust_ir.rs

+1
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ pub enum WellKnownTrait {
278278
DispatchFromDyn,
279279
Tuple,
280280
Pointee,
281+
FnPtr,
281282
}
282283

283284
chalk_ir::const_visit!(WellKnownTrait);

chalk-solve/src/wf.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,8 @@ where
437437
| WellKnownTrait::DiscriminantKind
438438
| WellKnownTrait::Generator
439439
| WellKnownTrait::Pointee
440-
| WellKnownTrait::Tuple => false,
440+
| WellKnownTrait::Tuple
441+
| WellKnownTrait::FnPtr => false,
441442
};
442443

443444
if is_legal {

tests/test/functions.rs

+71-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ fn function_implement_fn_traits() {
6666
impl Clone for Ty { }
6767

6868
opaque type MyOpaque: Clone = Ty;
69-
7069
}
7170

7271
// Simple test: make sure a fully monomorphic type implements FnOnce
@@ -246,3 +245,74 @@ fn function_implement_fn_traits() {
246245
}
247246
}
248247
}
248+
249+
#[test]
250+
fn functions_implement_fn_ptr_trait() {
251+
test! {
252+
program {
253+
#[lang(fn_ptr_trait)]
254+
trait FnPtr {}
255+
256+
closure closure_ty(self,) {}
257+
fn fn_def();
258+
}
259+
260+
goal {
261+
fn(()) -> (): FnPtr
262+
} yields {
263+
expect![[r#"Unique"#]]
264+
}
265+
266+
goal {
267+
unsafe fn(): FnPtr
268+
} yields {
269+
expect![[r#"Unique"#]]
270+
}
271+
272+
goal {
273+
extern "C" fn(u32, ...): FnPtr
274+
} yields {
275+
expect![[r#"Unique"#]]
276+
}
277+
278+
goal {
279+
for<'a> fn(&'a ()): FnPtr
280+
} yields {
281+
expect![[r#"Unique"#]]
282+
}
283+
284+
goal {
285+
forall<T, U> {
286+
fn(T) -> U: FnPtr
287+
}
288+
} yields {
289+
expect![[r#"Unique"#]]
290+
}
291+
292+
goal {
293+
i32: FnPtr
294+
} yields {
295+
expect![[r#"No possible solution"#]]
296+
}
297+
298+
goal {
299+
closure_ty: FnPtr
300+
} yields {
301+
expect![[r#"No possible solution"#]]
302+
}
303+
304+
goal {
305+
fn_def: FnPtr
306+
} yields {
307+
expect![[r#"No possible solution"#]]
308+
}
309+
310+
goal {
311+
exists<T> {
312+
T: FnPtr
313+
}
314+
} yields {
315+
expect![[r#"Ambiguous; no inference guidance"#]]
316+
}
317+
}
318+
}

0 commit comments

Comments
 (0)