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

Move handling of #[nested] to Visitor #67

Merged
merged 1 commit into from
Oct 7, 2019
Merged

Move handling of #[nested] to Visitor #67

merged 1 commit into from
Oct 7, 2019

Conversation

taiki-e
Copy link
Owner

@taiki-e taiki-e commented Oct 6, 2019

In the current implementation, enum is generated for each #[auto_enum] and #[nested] is only effective on the last expression of each branch. This PR changes #[nested] to be applicable to all branches in each branch.

#[nested] can be used basically in the same place as #[auto_enum], except that #[nested] cannot be used in functions.

Examples

#[auto_enum(Iterator)]
let z = if x {
    #[nested]
    let z = if y { 
        iter.map(|i| /* do something */)
    } else {
        iter.flat_map(|i| /* do something */)
    };
    // do something
    z
} else {
    std::iter::empty()
}
#[auto_enum(Iterator)]
let z = if x {
    #[nested]
    let z = match y { 
        Some(iter) => iter.flat_map(|i| /* do something */),
        None => make_new_iter().map(|i| /* do something */),
    };
    // do something
    z
} else {
    std::iter::empty()
}

Closes #64

@taiki-e taiki-e added the breaking-change This proposes a breaking change label Oct 6, 2019
@taiki-e taiki-e added this to the v0.7 milestone Oct 6, 2019
@taiki-e taiki-e force-pushed the nested branch 2 times, most recently from 596d503 to d8fddc9 Compare October 6, 2019 03:09
@taiki-e taiki-e force-pushed the nested branch 2 times, most recently from dc4d96f to 518e1b6 Compare October 7, 2019 16:29
@taiki-e taiki-e changed the title Move handling of #[nested] to Visitor core: Move handling of #[nested] to Visitor Oct 7, 2019
@taiki-e taiki-e changed the title core: Move handling of #[nested] to Visitor Move handling of #[nested] to Visitor Oct 7, 2019
@taiki-e
Copy link
Owner Author

taiki-e commented Oct 7, 2019

bors r+

bors bot added a commit that referenced this pull request Oct 7, 2019
67: Move handling of #[nested] to Visitor r=taiki-e a=taiki-e

In the current implementation, enum is generated for each `#[auto_enum]` and `#[nested]` is only effective on the last expression of each branch. This PR changes `#[nested]` to be applicable to all branches in each branch.

`#[nested]` can be used basically in the same place as `#[auto_enum]`, except that `#[nested]` cannot be used in functions.

### Examples

```rust
#[auto_enum(Iterator)]
let z = if x {
    #[nested]
    let z = if y { 
        iter.map(|i| /* do something */)
    } else {
        iter.flat_map(|i| /* do something */)
    };
    // do something
    z
} else {
    std::iter::empty()
}
```

```rust
#[auto_enum(Iterator)]
let z = if x {
    #[nested]
    let z = match y { 
        Some(iter) => iter.flat_map(|i| /* do something */),
        None => make_new_iter().map(|i| /* do something */),
    };
    // do something
    z
} else {
    std::iter::empty()
}
```

Closes #64

70: Enable std::future::Future support only in 1.36 or later r=taiki-e a=taiki-e



Co-authored-by: Taiki Endo <[email protected]>
@bors
Copy link
Contributor

bors bot commented Oct 7, 2019

Build succeeded

  • style (clippy)
  • style (rustdoc)
  • style (rustfmt)
  • test (1.31.0)
  • test (beta)
  • test (nightly)
  • test (stable)

@bors bors bot merged commit 1a40785 into master Oct 7, 2019
@bors bors bot deleted the nested branch October 7, 2019 17:32
@Boscop
Copy link

Boscop commented Oct 7, 2019

@taiki-e Thanks! Does this mean that no matter how many nested levels there are (#[nested] within #[nested]), only 1 enum will be generated (all branches' types (all leaves of the branch-tree) will be unified into 1 enum)?

@taiki-e
Copy link
Owner Author

taiki-e commented Oct 7, 2019

@Boscop

Does this mean that no matter how many nested levels there are (#[nested] within #[nested]), only 1 enum will be generated (all branches' types (all leaves of the branch-tree) will be unified into 1 enum)?

Yeah, #[nested] is a marker that indicates which expression should be wrapped, and has no role in creating an enum.

For example, the example in description of this PR generates the following code:

let z = {
    // 1 enum with 3 variants is generated.
    enum Enum<V1, V2, V3> {
        V1(V1),
        V2(V2),
        V3(V3),
    }
    // impl<V1, V2, V3> Iterator for Enum<V1, V2, V3> { ...
    if x {
        // If #[nested] is contained in a branch, the generation of 
        // a variant that wrap this entire branch is skipped.
        let z = if y {
            // Instead, each branch of the expression that #[nested]
            // is used is wrapped with a variant.
            Enum::V2(iter.map(|i| /* ... */))
        } else {
            Enum::V3(iter.flat_map(|i| /* ... */))
        };
        z
    } else {
        // Expressions that do not contain #[nested] are wrapped directly.
        Enum::V1(std::iter::empty())
    }
}

Also, if there is extra wrapping such as the following code, a compilation error will occur.

  match e {
        0 => Enum::A(0_u8),
        _ => Enum::B(match e {
            1 => Enum::C(0_u16),
            _ => Enum::D(0_u32),
        }),
    }

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=acc7936b1d54de286eb018a7b72a06ff

@taiki-e taiki-e added the A-auto_enum Area: #[auto_enum] label Apr 21, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-auto_enum Area: #[auto_enum] breaking-change This proposes a breaking change
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support #[nested] for nested if-exprs, to only generate 1 enum type
2 participants