]> git.lizzy.rs Git - rust.git/commitdiff
Don't canonicalize self type when querying FnOnce signature
authorJonas Schievink <jonas.schievink@ferrous-systems.com>
Tue, 8 Nov 2022 17:05:07 +0000 (18:05 +0100)
committerJonas Schievink <jonas.schievink@ferrous-systems.com>
Tue, 8 Nov 2022 17:05:07 +0000 (18:05 +0100)
crates/hir-ty/src/lib.rs
crates/hir/src/lib.rs
crates/ide/src/signature_help.rs

index ad33053ad095f5fe2d3d4475e9eb833fedbe3628..39514fc44e6c8091849b73b3d9c06549ba585b7b 100644 (file)
@@ -523,7 +523,7 @@ fn try_fold_free_var_lifetime(
 }
 
 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();
index 9d77f343bc5756b164eaef4bc4d64855feacc8d9..cbbcaebb428554a107ffcec8babdac21f3efac15 100644 (file)
@@ -2997,8 +2997,7 @@ pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
             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,
index 7486b20293a664b7fc048dc247332ff7118f8491..e7412d27faf446452a33962d6e70ca5220cc1122 100644 (file)
@@ -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
+            "#]],
+        );
     }
 }