- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.9k
          TypeVisitor: use std::ops::ControlFlow instead of bool
          #78182
        
          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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks.
Some nitpicks and suggestion but this is already looking a lot clearer to me ❤️
I do have to admit that my brain ended up skipping over some bool  -> ControlFlow conversions so hopefully I didn't accidentially miss anything 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's weird, why are we only visiting here if cond.visit_with(...) returns true?
Is this a preexisting bug? cc @oli-obk @jonas-schievink maybe
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yea this looks wrong. I don't know why it would be this way around. I mean this is essentially cond.visit_with(visitor) && {...} which is not something that is ever used anywhere
        
          
                compiler/rustc_middle/src/ty/fold.rs
              
                Outdated
          
        
      There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it might make sense to introduce a newtype here in the future, so this can be visit_with(...).break_value() == Some(FoundFlags).
Not part of this PR though
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, we probably want to store self.found in ControlFlow::Break here.
(also not part of this PR)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That folder seems weird to me, why are we storing the params in a hashmap if we only care about if there is more than one of them?
Using an option is probably more appropriate here but whatever 🤷 Isn't really relevant for this PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting that we aren't ignoring ReStatic here.
6d4777b    to
    8e58212      
    Compare
  
    8e58212    to
    e0f17c2      
    Compare
  
            
          
                compiler/rustc_privacy/src/lib.rs
              
                Outdated
          
        
      There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these are very common. Maybe we should have a ControlFlow::break_if(some_bool) and ControlFlow::continue_if(some_bool) for convenience? Or will that become infeasible with types other than ()?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, I think adding these methods make sense. I am not yet sure how to generalize them to deal with types other than ControlFlow<(), ()>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There has been almost no thought put into what methods the ControlFlow type should have, so if you come up with reasonable ones definitely add them.  It used to be an internal implementation detail, so doesn't even have the usual combinators.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@scottmcm I'd say definitely is_break and is_continue (name to be bikeshed of course). I'll file a PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ControlFlow should probably be #[must_use] so we'd be forced to use let _ =  here, but that's for another PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, making it #[must_use] seems like a good idea to me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I missed this in my review, but it seems weird to not propagate ControlFlow::Break here, I guess that this visitor never actually wants to break early so it is fine but it does seem strange.
Another reason for custom break types as we could use ! here to make this part of the API
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Opened #78202
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another thing you could consider to avoid the conversation on the type would be to just mark the methods on the trait as #[must_use].  It looks like that works even for calls on concrete things that don't copy the attribute to their implementation.  Probably still not this PR, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This alos looks like a candidate for returning a value via Break
| This PR is awesome (and exposes so many issues of different sublety | 
e0f17c2    to
    3ef1e8f      
    Compare
  
    3ef1e8f    to
    e14a5d8      
    Compare
  
    
      
        
              This comment has been minimized.
        
        
      
    
  This comment has been minimized.
e14a5d8    to
    901c1f4      
    Compare
  
    | @bors r+ | 
| 📌 Commit 901c1f446e22f1d067d2c0948b95fdd5ebe3d39d has been approved by  | 
| @bors r- I guess we should wait on the FCP 😅 | 
      
        
              This comment has been minimized.
        
        
      
    
  This comment has been minimized.
3244777    to
    9433eb8      
    Compare
  
    | @bory r=lcnr,oli-obk | 
      
        
              This comment has been minimized.
        
        
      
    
  This comment has been minimized.
| @bors r=lcnr,oli-obk rollup=never | 
| 📌 Commit 9433eb8 has been approved by  | 
| ☀️ Test successful - checks-actions | 
fix `super_visit_with` for `Terminator` fixes rust-lang#78182 (comment) r? `@oli-obk` cc `@LeSeulArtichaut`
…m-basics, r=m-ou-se Stabilize `ops::ControlFlow` (just the type) Tracking issue: rust-lang#75744 (which also tracks items *not* closed by this PR). With the new `?` desugar implemented, [it's no longer possible to mix `Result` and `ControlFlow`](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=13feec97f5c96a9d791d97f7de2d49a6). (At the time of making this PR, godbolt was still on the 2021-05-01 nightly, where you can see that [the mixing example compiled](https://rust.godbolt.org/z/13Ke54j16).) That resolves the only blocker I know of, so I'd like to propose that `ControlFlow` be considered for stabilization. Its basic existence was part of rust-lang/rfcs#3058, where it got a bunch of positive comments (examples [1](rust-lang/rfcs#3058 (comment)) [2](rust-lang/rfcs#3058 (review)) [3](rust-lang/rfcs#3058 (comment)) [4](rust-lang/rfcs#3058 (comment))). Its use in the compiler has been well received (rust-lang#78182 (comment)), and there are ecosystem updates interested in using it (rust-itertools/itertools#469 (comment), jonhoo/rust-imap#194). As this will need an FCP, picking a libs member manually: r? `@m-ou-se` ## Stabilized APIs ```rust #[derive(Debug, Clone, Copy, PartialEq)] pub enum ControlFlow<B, C = ()> { /// Exit the operation without running subsequent phases. Break(B), /// Move on to the next phase of the operation as normal. Continue(C), } ``` As well as using `?` on a `ControlFlow<B, _>` in a function returning `ControlFlow<B, _>`. (Note, in particular, that there's no `From::from`-conversion on the `Break` value, the way there is for `Err`s.) ## Existing APIs *not* stabilized here All the associated methods and constants: `break_value`, `is_continue`, `map_break`, [`CONTINUE`](https://doc.rust-lang.org/nightly/std/ops/enum.ControlFlow.html#associatedconstant.CONTINUE), etc. Some of the existing methods in nightly seem reasonable, some seem like they should be removed, and some need more discussion to decide. But none of them are *essential*, so [as in the RFC](https://rust-lang.github.io/rfcs/3058-try-trait-v2.html#methods-on-controlflow), they're all omitted from this PR. They can be considered separately later, as further usage demonstrates which are important.
…m-basics, r=m-ou-se Stabilize `ops::ControlFlow` (just the type) Tracking issue: rust-lang#75744 (which also tracks items *not* closed by this PR). With the new `?` desugar implemented, [it's no longer possible to mix `Result` and `ControlFlow`](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=13feec97f5c96a9d791d97f7de2d49a6). (At the time of making this PR, godbolt was still on the 2021-05-01 nightly, where you can see that [the mixing example compiled](https://rust.godbolt.org/z/13Ke54j16).) That resolves the only blocker I know of, so I'd like to propose that `ControlFlow` be considered for stabilization. Its basic existence was part of rust-lang/rfcs#3058, where it got a bunch of positive comments (examples [1](rust-lang/rfcs#3058 (comment)) [2](rust-lang/rfcs#3058 (review)) [3](rust-lang/rfcs#3058 (comment)) [4](rust-lang/rfcs#3058 (comment))). Its use in the compiler has been well received (rust-lang#78182 (comment)), and there are ecosystem updates interested in using it (rust-itertools/itertools#469 (comment), jonhoo/rust-imap#194). As this will need an FCP, picking a libs member manually: r? `@m-ou-se` ## Stabilized APIs ```rust #[derive(Debug, Clone, Copy, PartialEq)] pub enum ControlFlow<B, C = ()> { /// Exit the operation without running subsequent phases. Break(B), /// Move on to the next phase of the operation as normal. Continue(C), } ``` As well as using `?` on a `ControlFlow<B, _>` in a function returning `ControlFlow<B, _>`. (Note, in particular, that there's no `From::from`-conversion on the `Break` value, the way there is for `Err`s.) ## Existing APIs *not* stabilized here All the associated methods and constants: `break_value`, `is_continue`, `map_break`, [`CONTINUE`](https://doc.rust-lang.org/nightly/std/ops/enum.ControlFlow.html#associatedconstant.CONTINUE), etc. Some of the existing methods in nightly seem reasonable, some seem like they should be removed, and some need more discussion to decide. But none of them are *essential*, so [as in the RFC](https://rust-lang.github.io/rfcs/3058-try-trait-v2.html#methods-on-controlflow), they're all omitted from this PR. They can be considered separately later, as further usage demonstrates which are important.
Implements MCP rust-lang/compiler-team#374.
Blocked on FCP in rust-lang/compiler-team#374.
r? @lcnr cc @jonas-schievink