Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: wildcards in tuple struct patterns #552

Closed
ColonelJ opened this issue Jan 4, 2015 · 7 comments
Closed

Feature request: wildcards in tuple struct patterns #552

ColonelJ opened this issue Jan 4, 2015 · 7 comments

Comments

@ColonelJ
Copy link

ColonelJ commented Jan 4, 2015

Allow wildcards in tuple structs to leave the majority of elements unspecified, which makes a lot of sense in tuple structs where the arity is never in question! This allows you to put the data you want to match on at the start (or the end) of the tuple struct, and simplify your code.

Here's some sample code to demonstrate what should be possible, and what's possible already with arrays:

#![feature(advanced_slice_patterns)]
struct Thing(int,int,int,int,int);

fn main() {
    let arr = [1i,2,3,4,5];
    println!("This array {}", match arr {
        [1,2,..] => "goes one two!", // This one works as standard
        [..,5] => "ends in a 5",
        [..,4,_] => "has a penultimate 4",
        [4,..,4] => "starts and ends in 4...",
        _ => "is a bit weird..."
    }); // This works already using advanced_slice_patterns feature!

    let thing = Thing(1,2,3,4,5);
    println!("This thing {}", match thing {
        Thing(1,2,..) => "goes one two!",
        Thing(..,5) => "ends in a 5",
        Thing(..,4,_) => "has a penultimate 4",
        Thing(4,..,4) => "starts and ends in 4...",
        _ => "is a bit weird..."
    }); // Currently only Thing(..) is supported
}
@ColonelJ ColonelJ changed the title Feature request: wildcards in tuple patterns Feature request: wildcards in tuple struct patterns Jan 4, 2015
@ColonelJ
Copy link
Author

ColonelJ commented Jan 4, 2015

I took this out from the main request, but it also makes sense to support this for regular tuples:

let quint = (1i,2i,3i,4i,5i);
    println!("This quintet {}", match quint {
        (1,2,..) => "goes one two!",
        (..,5) => "ends in a 5",
        (..,4,_) => "has a penultimate 4",
        (4,..,4) => "starts and ends in 4...",
        _ => "is a bit weird..."
    });

@eddyb
Copy link
Member

eddyb commented Jan 4, 2015

This seems doable for tuple structs, because, as you have noted yourself, their arity is fixed.
We can thus "desugar" (not a true desugaring yet, because no CFG, but we can still do some pattern transformations in match checking) Thing(1, 2, ..) into Thing(1, 2, _, _, _).
I am almost positive Thing(4, ..middle, 4) would then be possible, resulting in Thing(4, a, b, c, 4) ... let middle = (a, b, c);.

As for tuples, that's a different story entirely, unless a match block with tuple wildcards is required to have a known type for the discriminator. In that case, everything that applies to tuple structs also applies to tuples.
Otherwise, it requires VG support in inference (relating/unifying types would have to understand a type like (T, ..U, V) where U is known to be a tuple, but its arity is unknown).

cc @nikomatsakis can you confirm we can do this? (modulo that VG part)

@SimonSapin
Copy link
Contributor

As for tuples, that's a different story entirely, unless a match block with tuple wildcards is required to have a known type for the discriminator.

Tuples of different arity are different types, and the value being matched has a single type, so all arities are known at compile time.

@eddyb
Copy link
Member

eddyb commented Jan 4, 2015

@SimonSapin I was talking about type inference, the following example works today:

match std::default::Default::default() {
    (1, 2, 3i) => 42,
    (x, y, z) => x + y + z
}

There is a single complete type there, int, the type of 3i.
Both match arm patterns have (_, _, _) as types, but everything gets inferred correctly, because the arity is fixed, even though the type of the discriminant is not known before inference.

@nwin
Copy link

nwin commented Feb 24, 2015

Any news on this? It is really a bit inconsistent that you sometimes may use .. and sometimes _.

    struct TPerson(&'static str, u8);
    struct SPerson { 
        name: &'static str,
        age: u8
    }
    fn main() {
        let person = TPerson("John", 39);
        let TPerson (name, ..) = person; // Invalid
        let person = SPerson {name:"John", age:39};
        let SPerson {name, ..} = person; // Valid
    }

@Stebalien
Copy link
Contributor

Triage: Fixed by #1492

@alexcrichton
Copy link
Member

Yay!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants