Skip to content

typestate sees break as applying to the outermost loop #2642

Closed

Description

@paulstansifer

The following code compiles (as expected):

fn main() {
    let _x: uint = loop { };
}

However, this code does not, as if the break were breaking out of the outer loop:

fn main() {
    let _x: uint = loop { loop { break; } };
}

Activity

  1. nikomatsakis commented on Jun 18, 2012

    @nikomatsakis
    Contributor

    this may be a liveness bug?

  2. catamorphism commented on Jun 18, 2012

    @catamorphism
    Contributor

    Maybe, but I'm pretty sure I know what the bug is if it's in typestate. @paulstansifer , can you post the error message?

  3. nikomatsakis commented on Jun 18, 2012

    @nikomatsakis
    Contributor

    actually I think this is neither liveness nor typestate but rather typeck and something off in the (rather hokey) way that it tracks the notion of "bottom".

  4. nikomatsakis commented on Jun 18, 2012

    @nikomatsakis
    Contributor

    this is the error that I see:

    /Users/nmatsakis/tmp/issue-2642.rs:2:19: 2:43 error: mismatched types: expected `uint` but found `()` (uint vs ())
    /Users/nmatsakis/tmp/issue-2642.rs:2     let _x: uint = loop { loop { break; } };
                                                            ^~~~~~~~~~~~~~~~~~~~~~~~
    
    
  5. catamorphism commented on Jun 18, 2012

    @catamorphism
    Contributor

    Yeah, not a typestate error. I can still take a look, though.

  6. nikomatsakis commented on Jun 18, 2012

    @nikomatsakis
    Contributor

    To be honest, I am not sure that the type system ought to be in the business of tracking bottom.

  7. paulstansifer commented on Jun 18, 2012

    @paulstansifer
    ContributorAuthor

    Oops, sorry folks. That's the same as the error I get.

  8. paulstansifer commented on Jun 18, 2012

    @paulstansifer
    ContributorAuthor

    It's really useful if you want to return from inside an otherwise infinite loop, which is what led me to this bug.

  9. nikomatsakis commented on Jun 18, 2012

    @nikomatsakis
    Contributor

    but why are you "assigning" the loop to a local variable in the first place?

  10. nikomatsakis commented on Jun 18, 2012

    @nikomatsakis
    Contributor

    it seems to me that loops and complex constructs that may or may not be bottom should just have unit type. Something like ret or what have you can still have bottom type.

  11. paulstansifer commented on Jun 18, 2012

    @paulstansifer
    ContributorAuthor

    I probably should've reduced it to an example that looks more like the code I'm interested in:

    fn f() -> uint {
      loop {
        if some_cond { ret 8u; }
        loop { break; }
      }
    }

    In this case, we need bottom to acknowledge that nothing will ever fall off the end of the outer loop, preventing the need for a dummy, dead code ret statement.

  12. eholk commented on Jun 18, 2012

    @eholk
    Contributor

    I think I usually just use fail if I need to convince the compiler that some code will never run.

  13. catamorphism commented on Jun 19, 2012

    @catamorphism
    Contributor

    Yes, but the point of introducing loop was to make it possible to omit fails in some common cases... so I'm with Paul at least until I look at the typeck code and decide it's too hard to fix ;-)

  14. nikomatsakis commented on Jun 19, 2012

    @nikomatsakis
    Contributor

    Paul's example is more convincing. I guess we have to make it work due to the fact that loops are expressions and can appear in tail position in a block. sigh

  15. added a commit that references this issue on Nov 6, 2022
  16. added a commit that references this issue on Jan 6, 2023
  17. added a commit that references this issue on Nov 19, 2025
  18. added a commit that references this issue on Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions