Add make_tuple
tactic
This commit is contained in:
parent
8bd30e9b3f
commit
be6f8e2648
@ -4321,8 +4321,10 @@ pub fn type_arguments(&self) -> impl Iterator<Item = Type> + '_ {
|
|||||||
self.ty
|
self.ty
|
||||||
.strip_references()
|
.strip_references()
|
||||||
.as_adt()
|
.as_adt()
|
||||||
|
.map(|(_, substs)| substs)
|
||||||
|
.or_else(|| self.ty.strip_references().as_tuple())
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(|(_, substs)| substs.iter(Interner))
|
.flat_map(|substs| substs.iter(Interner))
|
||||||
.filter_map(|arg| arg.ty(Interner).cloned())
|
.filter_map(|arg| arg.ty(Interner).cloned())
|
||||||
.map(move |ty| self.derived(ty))
|
.map(move |ty| self.derived(ty))
|
||||||
}
|
}
|
||||||
|
@ -311,6 +311,7 @@ pub fn term_search<DB: HirDatabase>(ctx: &TermSearchCtx<'_, DB>) -> Vec<Expr> {
|
|||||||
solutions.extend(tactics::impl_method(ctx, &defs, &mut lookup));
|
solutions.extend(tactics::impl_method(ctx, &defs, &mut lookup));
|
||||||
solutions.extend(tactics::struct_projection(ctx, &defs, &mut lookup));
|
solutions.extend(tactics::struct_projection(ctx, &defs, &mut lookup));
|
||||||
solutions.extend(tactics::impl_static_method(ctx, &defs, &mut lookup));
|
solutions.extend(tactics::impl_static_method(ctx, &defs, &mut lookup));
|
||||||
|
solutions.extend(tactics::make_tuple(ctx, &defs, &mut lookup));
|
||||||
|
|
||||||
// Discard not interesting `ScopeDef`s for speedup
|
// Discard not interesting `ScopeDef`s for speedup
|
||||||
for def in lookup.exhausted_scopedefs() {
|
for def in lookup.exhausted_scopedefs() {
|
||||||
|
@ -872,3 +872,61 @@ pub(super) fn impl_static_method<'a, DB: HirDatabase>(
|
|||||||
.filter_map(|(ty, exprs)| ty.could_unify_with_deeply(db, &ctx.goal).then_some(exprs))
|
.filter_map(|(ty, exprs)| ty.could_unify_with_deeply(db, &ctx.goal).then_some(exprs))
|
||||||
.flatten()
|
.flatten()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Make tuple tactic
|
||||||
|
///
|
||||||
|
/// Attempts to create tuple types if any are listed in types wishlist
|
||||||
|
///
|
||||||
|
/// Updates lookup by new types reached and returns iterator that yields
|
||||||
|
/// elements that unify with `goal`.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
/// * `ctx` - Context for the term search
|
||||||
|
/// * `defs` - Set of items in scope at term search target location
|
||||||
|
/// * `lookup` - Lookup table for types
|
||||||
|
pub(super) fn make_tuple<'a, DB: HirDatabase>(
|
||||||
|
ctx: &'a TermSearchCtx<'a, DB>,
|
||||||
|
_defs: &'a FxHashSet<ScopeDef>,
|
||||||
|
lookup: &'a mut LookupTable,
|
||||||
|
) -> impl Iterator<Item = Expr> + 'a {
|
||||||
|
let db = ctx.sema.db;
|
||||||
|
let module = ctx.scope.module();
|
||||||
|
|
||||||
|
lookup
|
||||||
|
.types_wishlist()
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|ty| ty.is_tuple())
|
||||||
|
.filter_map(move |ty| {
|
||||||
|
// Double check to not contain unknown
|
||||||
|
if ty.contains_unknown() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore types that have something to do with lifetimes
|
||||||
|
if ctx.config.enable_borrowcheck && ty.contains_reference(db) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Early exit if some param cannot be filled from lookup
|
||||||
|
let param_exprs: Vec<Vec<Expr>> =
|
||||||
|
ty.type_arguments().map(|field| lookup.find(db, &field)).collect::<Option<_>>()?;
|
||||||
|
|
||||||
|
let exprs: Vec<Expr> = param_exprs
|
||||||
|
.into_iter()
|
||||||
|
.multi_cartesian_product()
|
||||||
|
.map(|params| {
|
||||||
|
let tys: Vec<Type> = params.iter().map(|it| it.ty(db)).collect();
|
||||||
|
let tuple_ty = Type::new_tuple(module.krate().into(), &tys);
|
||||||
|
|
||||||
|
let expr = Expr::Tuple { ty: tuple_ty.clone(), params };
|
||||||
|
lookup.insert(tuple_ty, iter::once(expr.clone()));
|
||||||
|
expr
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Some(exprs)
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
|
.filter_map(|expr| expr.ty(db).could_unify_with_deeply(db, &ctx.goal).then_some(expr))
|
||||||
|
}
|
||||||
|
@ -253,4 +253,24 @@ fn f(a: &i32) -> f32 { a as f32 }
|
|||||||
fn g() { let a = &mut 1; let b: f32 = todo$0!(); }"#,
|
fn g() { let a = &mut 1; let b: f32 = todo$0!(); }"#,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_tuple_simple() {
|
||||||
|
check_assist(
|
||||||
|
term_search,
|
||||||
|
r#"//- minicore: todo, unimplemented
|
||||||
|
fn f() { let a = 1; let b = 0.0; let c: (i32, f64) = todo$0!(); }"#,
|
||||||
|
r#"fn f() { let a = 1; let b = 0.0; let c: (i32, f64) = (a, b); }"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_tuple_nested() {
|
||||||
|
check_assist(
|
||||||
|
term_search,
|
||||||
|
r#"//- minicore: todo, unimplemented
|
||||||
|
fn f() { let a = 1; let b = 0.0; let c: (i32, (i32, f64)) = todo$0!(); }"#,
|
||||||
|
r#"fn f() { let a = 1; let b = 0.0; let c: (i32, (i32, f64)) = (a, (a, b)); }"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user