Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit be6f8e2

Browse files
committed
Add make_tuple tactic
1 parent 8bd30e9 commit be6f8e2

File tree

4 files changed

+82
-1
lines changed

4 files changed

+82
-1
lines changed

crates/hir/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4321,8 +4321,10 @@ impl Type {
43214321
self.ty
43224322
.strip_references()
43234323
.as_adt()
4324+
.map(|(_, substs)| substs)
4325+
.or_else(|| self.ty.strip_references().as_tuple())
43244326
.into_iter()
4325-
.flat_map(|(_, substs)| substs.iter(Interner))
4327+
.flat_map(|substs| substs.iter(Interner))
43264328
.filter_map(|arg| arg.ty(Interner).cloned())
43274329
.map(move |ty| self.derived(ty))
43284330
}

crates/hir/src/term_search.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ pub fn term_search<DB: HirDatabase>(ctx: &TermSearchCtx<'_, DB>) -> Vec<Expr> {
311311
solutions.extend(tactics::impl_method(ctx, &defs, &mut lookup));
312312
solutions.extend(tactics::struct_projection(ctx, &defs, &mut lookup));
313313
solutions.extend(tactics::impl_static_method(ctx, &defs, &mut lookup));
314+
solutions.extend(tactics::make_tuple(ctx, &defs, &mut lookup));
314315

315316
// Discard not interesting `ScopeDef`s for speedup
316317
for def in lookup.exhausted_scopedefs() {

crates/hir/src/term_search/tactics.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,3 +872,61 @@ pub(super) fn impl_static_method<'a, DB: HirDatabase>(
872872
.filter_map(|(ty, exprs)| ty.could_unify_with_deeply(db, &ctx.goal).then_some(exprs))
873873
.flatten()
874874
}
875+
876+
/// # Make tuple tactic
877+
///
878+
/// Attempts to create tuple types if any are listed in types wishlist
879+
///
880+
/// Updates lookup by new types reached and returns iterator that yields
881+
/// elements that unify with `goal`.
882+
///
883+
/// # Arguments
884+
/// * `ctx` - Context for the term search
885+
/// * `defs` - Set of items in scope at term search target location
886+
/// * `lookup` - Lookup table for types
887+
pub(super) fn make_tuple<'a, DB: HirDatabase>(
888+
ctx: &'a TermSearchCtx<'a, DB>,
889+
_defs: &'a FxHashSet<ScopeDef>,
890+
lookup: &'a mut LookupTable,
891+
) -> impl Iterator<Item = Expr> + 'a {
892+
let db = ctx.sema.db;
893+
let module = ctx.scope.module();
894+
895+
lookup
896+
.types_wishlist()
897+
.clone()
898+
.into_iter()
899+
.filter(|ty| ty.is_tuple())
900+
.filter_map(move |ty| {
901+
// Double check to not contain unknown
902+
if ty.contains_unknown() {
903+
return None;
904+
}
905+
906+
// Ignore types that have something to do with lifetimes
907+
if ctx.config.enable_borrowcheck && ty.contains_reference(db) {
908+
return None;
909+
}
910+
911+
// Early exit if some param cannot be filled from lookup
912+
let param_exprs: Vec<Vec<Expr>> =
913+
ty.type_arguments().map(|field| lookup.find(db, &field)).collect::<Option<_>>()?;
914+
915+
let exprs: Vec<Expr> = param_exprs
916+
.into_iter()
917+
.multi_cartesian_product()
918+
.map(|params| {
919+
let tys: Vec<Type> = params.iter().map(|it| it.ty(db)).collect();
920+
let tuple_ty = Type::new_tuple(module.krate().into(), &tys);
921+
922+
let expr = Expr::Tuple { ty: tuple_ty.clone(), params };
923+
lookup.insert(tuple_ty, iter::once(expr.clone()));
924+
expr
925+
})
926+
.collect();
927+
928+
Some(exprs)
929+
})
930+
.flatten()
931+
.filter_map(|expr| expr.ty(db).could_unify_with_deeply(db, &ctx.goal).then_some(expr))
932+
}

crates/ide-assists/src/handlers/term_search.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,4 +253,24 @@ fn g() { let a = &1; let b: f32 = f(a); }"#,
253253
fn g() { let a = &mut 1; let b: f32 = todo$0!(); }"#,
254254
)
255255
}
256+
257+
#[test]
258+
fn test_tuple_simple() {
259+
check_assist(
260+
term_search,
261+
r#"//- minicore: todo, unimplemented
262+
fn f() { let a = 1; let b = 0.0; let c: (i32, f64) = todo$0!(); }"#,
263+
r#"fn f() { let a = 1; let b = 0.0; let c: (i32, f64) = (a, b); }"#,
264+
)
265+
}
266+
267+
#[test]
268+
fn test_tuple_nested() {
269+
check_assist(
270+
term_search,
271+
r#"//- minicore: todo, unimplemented
272+
fn f() { let a = 1; let b = 0.0; let c: (i32, (i32, f64)) = todo$0!(); }"#,
273+
r#"fn f() { let a = 1; let b = 0.0; let c: (i32, (i32, f64)) = (a, (a, b)); }"#,
274+
)
275+
}
256276
}

0 commit comments

Comments
 (0)