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

Allow attributes on match arms #12812

Merged
merged 1 commit into from
Apr 24, 2014
Merged

Allow attributes on match arms #12812

merged 1 commit into from
Apr 24, 2014

Conversation

sfackler
Copy link
Member

This is really only useful for #[cfg()]. For example:

enum Foo {
    Bar,
    Baz,
    #[cfg(blob)]
    Blob
}

fn match_foos(f: &Foo) {
    match *f {
        Bar => {}
        Baz => {}
        #[cfg(blob)]
        Blob => {}
    }
}

This is a kind of weird place to allow attributes, so it should probably
be discussed before merging.

@lilyball
Copy link
Contributor

I didn't know we allowed attributes on enum variants. Is there anything else that's not an item that we allow attributes on already.

@sfackler
Copy link
Member Author

They're also allowed on struct fields:

struct Foo {
   #[cfg(blah)]
   blah: int,
}

@lilyball
Copy link
Contributor

Interesting. But both of those things are still structural components of an item. Whereas an arm of a match is a component of an expression.

It seems to me that if I can have an enum on a match arm, I should be able to have an enum on an expression itself (or maybe I should say on a statement). Right now we have the cfg!() macro to accomplish the same thing, although that unfortunately won't work for match arms.

I guess I'm saying that I'm not opposed to this change, it just feels a little weird, and I'd be more comfortable if we went ahead and allowed #[cfg(foo)] on statements as well.

@brson
Copy link
Contributor

brson commented Mar 10, 2014

Is there a specific use case we're adding this for? Does it have workarounds?

@sfackler
Copy link
Member Author

I have a use case here in rust-openssl: https://github.com/sfackler/rust-openssl/blob/master/ssl/mod.rs#L61

Many distributions of OpenSSL compile out SSLv2 support, so rust-openssl has the ability to do that as well. The enum entry can be simply tagged with a #[cfg(sslv2)] attribute, but functions that match on the enum have to be duplicated entirely.

@flaper87
Copy link
Contributor

@sfackler you could have a static item that has the version of ssl and just duplicate the match:

if SSL_VERSION == 2 {
        match *self {
            Sslv2 => {return ffi::SSLv2_method();},
            _ => {}
        }
}

match *self {
        Sslv3 => {return ffi::SSLv3_method();},
        Tlsv1 => {return ffi::TLSv1_method();},
        Sslv23 => {return ffi::SSLv23_method();}
}

(obviously, not tested)

I'm not fully opposed to this change, though. I do agree with @kballard that it feels weird to have attributes for match arms and not for other things. Although, I'd prefer evaluate them in a case-by-case basis.

@sfackler
Copy link
Member Author

@flaper87 that wouldn't compile if Sslv2 or ffi::SSLv2_method don't exist, though which wouldn't if SSLv2 is turned off. You'd also run into a noncomprehensive match error on the second match block if Sslv2 does exist.

@flaper87
Copy link
Contributor

@sfackler I feel dumb today. 😢

You need the method to be duplicated in that case. So this change makes even more sense to avoid that much code duplication.

@eddyb
Copy link
Member

eddyb commented Mar 11, 2014

I have another usecase (although LLVM might not have the annotation functionality required here):

fn main() {
    for _ in range(0, large_number) {...}
}
// Gets desugared to something like this:
// (also similar to what many iterator adapters do internally)
fn main() {
    match range(0, large_number) {
        ref mut iter => loop {
            match iter.next() {
                Some(_) => {...}
                #[cold] // now we can mark this arm "cold".
                None => break
            }
        }
    }
}

@sfackler
Copy link
Member Author

How are people feeling about this? I'll close it if it seems too weird.

@lilyball
Copy link
Contributor

It seems weird, certainly, but also useful. I'm inclined to say go ahead and do it, but I wish there was a better way to achieve the same result without the weirdness.

@andrew-d
Copy link
Contributor

From someone just watching: I think it would be nice if this gets merged. It seems like it might be awkward to achieve matching on an enum in other ways while maintaining the nicety of having it warn you about an exhaustive match. Furthermore, from the examples above, even having two or three different combinations (e.g. SSLv2, TLS1.1 and TLS1.2 all being optional) means that implementing all the combinations individually seems impractical.

@flaper87
Copy link
Contributor

This PR should probably have an RFC (see #12963). This change and the one proposing attributes on statements could probably be proposed on the same RFC.

@huonw
Copy link
Member

huonw commented Mar 20, 2014

RFC'd rust-lang/rfcs#16; any more commentary should move there.

@huonw huonw closed this Mar 20, 2014
@sfackler sfackler reopened this Apr 23, 2014
@sfackler
Copy link
Member Author

Reopened and rebased. r?

@alexcrichton
Copy link
Member

Oh one thing I should mention is that we're trying to link commits to RFCs with just some words in the commit message, could you make sure this is at the bottom of the message:

RFC: 0008-match-arm-attributes

@sfackler
Copy link
Member Author

I'll add that when I finish bludgeoning the pretty printer into submission :(

RFC: 0008-match-arm-attributes
bors added a commit that referenced this pull request Apr 24, 2014
This is really only useful for #[cfg()]. For example:

```rust
enum Foo {
    Bar,
    Baz,
    #[cfg(blob)]
    Blob
}

fn match_foos(f: &Foo) {
    match *f {
        Bar => {}
        Baz => {}
        #[cfg(blob)]
        Blob => {}
    }
}
```

This is a kind of weird place to allow attributes, so it should probably
be discussed before merging.
@bors bors merged commit 1452c9c into rust-lang:master Apr 24, 2014
@sfackler sfackler deleted the attr-arm branch May 15, 2014 05:02
flip1995 pushed a commit to flip1995/rust that referenced this pull request May 17, 2024
Manually set library paths in .github/driver.sh

Fixes https://rust-lang.zulipchat.com/#narrow/stream/257328-clippy/topic/Windows.20CI.20failing

Rustup 1.27.1 no longer adds `[SYSROOT]/bin` to `PATH` by default - rust-lang/rustup#3825. This is fine for the packaged binaries since windows loads `dll`s from the folder the executable is in, but our built one is in a different folder

There's an environment variable to get the old behaviour back, but as it's deprecated and not much code I think returning to setting it manually is fine

changelog: none
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

Successfully merging this pull request may close these issues.

9 participants