rust-analyzer icon indicating copy to clipboard operation
rust-analyzer copied to clipboard

Feature request: convert tuple to a struct by creating a new struct type

Open kornelski opened this issue 3 years ago • 4 comments

I wish rust-analyzer had a code action to refactor this:

fn numberwang() -> (f32, bool) {
   let a = 1.;
   let b = true;
   (a, b)
}
let (x,y) = numberwang();

into this:

struct Untupled {
  x: f32,
  b: bool,
}

fn numberwang() -> Untupled {
   let x = 1.;
   let y = true;
   Untupled {a, b}
}
let Untupled {a:x, b:y} = numberwang();

I tend to be lazy and overuse tuples. They're convenient when I have 2-3 values to work with, but eventually I end up with a tuple of 7 values and lose track of which field is which. It'd be great to have a code action that I can point to a tuple instance, and it will replace it with a struct type, and follow all usages of this tuple (places where it has become a compile error, not all places that use the same types together) and replace them with the struct type too.

kornelski avatar Sep 02 '22 23:09 kornelski

I guess tracking uses would be hard, but even a minimal action would be useful: given a tuple expression:

(foo, bar, baz)

get variable names from it, their types, and generate a struct type with these name/type pairs:

struct Untupled { foo: FooType, bar: BarType, baz: BazType }

Converting tuple syntax into this mix of types and names requires too much copy-pasting.

kornelski avatar Sep 02 '22 23:09 kornelski

How can we retrive the variable names from tuples? It may be easy in the case of call with immediate destructurings, but not so in the general case.

ChayimFriedman2 avatar Sep 04 '22 08:09 ChayimFriedman2

if no heurstic applies we can just pick whatever, like field0, field1 ...

Veykril avatar Sep 04 '22 10:09 Veykril

I realize that if a tuple is constructed from more complex expressions then there won't be a clear name to pick. However, I find this pattern pretty common:

let foo = get_foo();
let bar = get_bar();
(foo, bar)

which gives the tuple literal some names to use.

kornelski avatar Sep 04 '22 10:09 kornelski

Just dropping my +1 in for this. The use case I have is successive refactoring: I'm working with some WGPU code, where I have several variables being created that depend on previous state. I've been selecting these, creating a function from them (which returns a tuple), and then converting those tuples into structs, so that I go from

let blah = blah;
let blah2 = something_with(&blah);

to

fn make_blahs() -> (Blah, Blah2) {
    let blah = blah;
    let blah2 = something_with(&blah);
    (blah, blah2)
}

to

struct BlahState {
    blah: Blah,
    blah2: Blah2,
}
impl BlahState {
    fn new() -> Self {
        let blah = blah;
        let blah2 = something_with(&blah);
        Self { blah, blah2 }
    }
}

I currently have to do the last step manually - a r-a tool to automate this would make my life much easier ^_^

philpax avatar Oct 02 '22 19:10 philpax