Unnamed repository; edit this file 'description' to name the repository.
Don't canonicalize self type when querying FnOnce signature
Jonas Schievink 2022-11-09
parent 977a029 · commit 9be0615
-rw-r--r--crates/hir-ty/src/lib.rs48
-rw-r--r--crates/hir/src/lib.rs3
-rw-r--r--crates/ide/src/signature_help.rs31
3 files changed, 54 insertions, 28 deletions
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index ad33053ad0..39514fc44e 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -523,7 +523,7 @@ where
}
pub fn callable_sig_from_fnonce(
- self_ty: &Canonical<Ty>,
+ self_ty: &Ty,
env: Arc<TraitEnvironment>,
db: &dyn HirDatabase,
) -> Option<CallableSig> {
@@ -531,27 +531,28 @@ pub fn callable_sig_from_fnonce(
let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?;
let output_assoc_type = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
- let mut kinds = self_ty.binders.interned().to_vec();
let b = TyBuilder::trait_ref(db, fn_once_trait);
if b.remaining() != 2 {
return None;
}
- let fn_once = b
- .push(self_ty.value.clone())
- .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len())
- .build();
- kinds.extend(fn_once.substitution.iter(Interner).skip(1).map(|x| {
- let vk = match x.data(Interner) {
- chalk_ir::GenericArgData::Ty(_) => {
- chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)
- }
- chalk_ir::GenericArgData::Lifetime(_) => chalk_ir::VariableKind::Lifetime,
- chalk_ir::GenericArgData::Const(c) => {
- chalk_ir::VariableKind::Const(c.data(Interner).ty.clone())
- }
- };
- chalk_ir::WithKind::new(vk, UniverseIndex::ROOT)
- }));
+ let fn_once = b.push(self_ty.clone()).fill_with_bound_vars(DebruijnIndex::INNERMOST, 0).build();
+ let kinds = fn_once
+ .substitution
+ .iter(Interner)
+ .skip(1)
+ .map(|x| {
+ let vk = match x.data(Interner) {
+ chalk_ir::GenericArgData::Ty(_) => {
+ chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)
+ }
+ chalk_ir::GenericArgData::Lifetime(_) => chalk_ir::VariableKind::Lifetime,
+ chalk_ir::GenericArgData::Const(c) => {
+ chalk_ir::VariableKind::Const(c.data(Interner).ty.clone())
+ }
+ };
+ chalk_ir::WithKind::new(vk, UniverseIndex::ROOT)
+ })
+ .collect::<Vec<_>>();
// FIXME: chalk refuses to solve `<Self as FnOnce<^0.0>>::Output == ^0.1`, so we first solve
// `<Self as FnOnce<^0.0>>` and then replace `^0.0` with the concrete argument tuple.
@@ -563,21 +564,16 @@ pub fn callable_sig_from_fnonce(
Some(Solution::Unique(vars)) => vars.value.subst,
_ => return None,
};
- let args = subst.at(Interner, self_ty.binders.interned().len()).ty(Interner)?;
+ let args = subst.at(Interner, 0).ty(Interner)?;
let params = match args.kind(Interner) {
chalk_ir::TyKind::Tuple(_, subst) => {
subst.iter(Interner).filter_map(|arg| arg.ty(Interner).cloned()).collect::<Vec<_>>()
}
_ => return None,
};
- if params.iter().any(|ty| ty.is_unknown()) {
- return None;
- }
- let fn_once = TyBuilder::trait_ref(db, fn_once_trait)
- .push(self_ty.value.clone())
- .push(args.clone())
- .build();
+ let fn_once =
+ TyBuilder::trait_ref(db, fn_once_trait).push(self_ty.clone()).push(args.clone()).build();
let projection =
TyBuilder::assoc_type_projection(db, output_assoc_type, Some(fn_once.substitution.clone()))
.build();
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 9d77f343bc..cbbcaebb42 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -2997,8 +2997,7 @@ impl Type {
TyKind::Function(_) => Callee::FnPtr,
TyKind::FnDef(..) => Callee::Def(self.ty.callable_def(db)?),
_ => {
- let ty = hir_ty::replace_errors_with_variables(&self.ty);
- let sig = hir_ty::callable_sig_from_fnonce(&ty, self.env.clone(), db)?;
+ let sig = hir_ty::callable_sig_from_fnonce(&self.ty, self.env.clone(), db)?;
return Some(Callable {
ty: self.clone(),
sig,
diff --git a/crates/ide/src/signature_help.rs b/crates/ide/src/signature_help.rs
index 7486b20293..e7412d27fa 100644
--- a/crates/ide/src/signature_help.rs
+++ b/crates/ide/src/signature_help.rs
@@ -1345,5 +1345,36 @@ fn f<F: FnOnce(u8, u16) -> i32>(f: F) {
^^ ---
"#]],
);
+ check(
+ r#"
+fn f<T, F: FnOnce(&T, u16) -> &T>(f: F) {
+ f($0)
+}
+"#,
+ expect![[r#"
+ (&T, u16) -> &T
+ ^^ ---
+ "#]],
+ );
+ }
+
+ #[test]
+ fn regression_13579() {
+ check(
+ r#"
+fn f() {
+ take(2)($0);
+}
+
+fn take<C, Error>(
+ count: C
+) -> impl Fn() -> C {
+ move || count
+}
+"#,
+ expect![[r#"
+ () -> i32
+ "#]],
+ );
}
}