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

Better error message for "error: break' outside of loop" inside of do' inside of `for' #3064

Closed
bblum opened this issue Jul 31, 2012 · 17 comments
Labels
A-frontend Area: Compiler frontend (errors, parsing and HIR) E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.

Comments

@bblum
Copy link
Contributor

bblum commented Jul 31, 2012

fn main() {
    let vec = ~[some(())];
    for vec::each(vec) |slot| {
        do slot.iter |bucket| {
            break;
        }
    }
}

fails to compile, though I claim it should, and be the same as:

fn main() {
    let vec = ~[some(())];
    for vec::each(vec) |slot| {
        alt slot {
            some(bucket) { break; }
            none { }
        }
    }
}
@mitsuhiko
Copy link
Contributor

The issue also exists for loop constructs.

@nikomatsakis
Copy link
Contributor

You cannot break from a do because do does not require any sort of protocol, unlike for. The best we could do is to make break equivalent to "return" from the closure---which perhaps we ought to do, but I am not sure. There is no reason to think that the function will observe "break-like" semantics.

@bblum
Copy link
Contributor Author

bblum commented Oct 22, 2012

oh, huh, for some reason I forgot that there was another closure going on here. Yeah, this is correct behaviour. Maybe a better error message.

@mitsuhiko
Copy link
Contributor

The way it works for ruby is that the interpreter sets jump targets in the method frame. Each black executed from the stack will look at the method's frame to find where to jump to for continue/break/return.

@pnkfelix
Copy link
Member

Here is the syntax modernized version of the examples.

    fn foo1() {
        let vec = ~[Some(())];
        for vec::each(vec) |slot| {
            do slot.each |_bucket| {
                break; // error: `break` outside of loop
            }
        }
    }

    fn foo2() {
        let vec = ~[Some(())];
        for vec::each(vec) |slot| {
            match *slot {
                Some(_bucket) => { break; }
                None => { }
            }
        }

I vote for either leaving things as is (and accept the odd error message as a consequence of integration of light-weight closure syntax), or finding some way to "improve" the error message (though it is not clear how best to do so).

@pnkfelix
Copy link
Member

Not critical for 0.6; de-milestoning

@pnkfelix
Copy link
Member

(there are of course other options. e.g. we could look into mitsuhiko's suggestion and change the calling convention so that invoking a closure implicitly passes along some number >1 of continuations, corresponding to different places control should shift in response to continue vs break vs return; but we would probably need to see some very convincing use-cases to motivate such a change.)

@catamorphism
Copy link
Contributor

@pnkfelix - Changing the calling convention is what might be needed in order to make labelled-break-out-of-a-for work (see #4131). I'm not sure whether we need to ever fix that, though.

@nikomatsakis
Copy link
Contributor

Changing the calling convention is not needed. If we can return out of the whole function, we can certainly break out of a subloop---you just break set a variable in your local stack indicating the point you wish to break to. To handle do, on the other hand, is more complex.

@nikomatsakis
Copy link
Contributor

(Let me rephrase: we cannot handle do. That's the whole point of do is that it doesn't introduce any syntactic sugar or anything)

@graydon
Copy link
Contributor

graydon commented May 15, 2013

Yeah, I'm sensing this is more of a WONTFIX. We're landing those enhancements to the for-protocol we can (eg. 3e0400f / #6223 ) but I think encoding arbitrary loop-label break targets into it as in #4131 is likely pushing it beyond the breaking point. And I agree with @nikomatsakis that there's not much we can do about do without demanding that it acquire a protocol-and-rewriting of its own (which would affect all users, on the off chance that they're called inside a loop)

@bblum
Copy link
Contributor Author

bblum commented May 15, 2013

I agree that the functionality shouldn't be supported, but you don't think a less confusing error message would be doable?

@nikomatsakis
Copy link
Contributor

@graydon to be clear, I think that break to an arbitrary target from inside a for loop ought to work---at least there is no theoretical impediment, no changes to the protocol are needed etc---but that's not what this bug is about

@huonw
Copy link
Member

huonw commented Jul 23, 2013

Visiting for triage, the error message is still the same.

@bstrie
Copy link
Contributor

bstrie commented Jul 23, 2013

I think this should be obviated by the plan for the new for semantics, but let's not close until that's landed.

@bblum
Copy link
Contributor Author

bblum commented Jul 23, 2013

I expect the need for the error message will still exist.

@alexcrichton
Copy link
Member

Even with the new for loop, this is still an issue

fn foo(f: ||) {}  

fn main() {       
    loop {        
        do foo {  
            break;
        }         
    }             
}                 

That still gives the same error message, which is still misleading because it's inside of a loop

RalfJung pushed a commit to RalfJung/rust that referenced this issue Sep 25, 2023
celinval added a commit to celinval/rust-dev that referenced this issue Jun 4, 2024
The `reverse_postorder` function used before is internal to the compiler
and reflects the internal body representation.

Besides that, I would like to introduce transformation on the top of
SMIR body, which will break the 1:1 relationship between basic blocks
from internal body and monomorphic body from StableMIR.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-frontend Area: Compiler frontend (errors, parsing and HIR) E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.
Projects
None yet
Development

No branches or pull requests

9 participants