The rest of it is about where to put the sharp edges: Can I break-e from a switch-e wherever I might consider doing return from a method/lambda? Or does break-e have extra restrictions to prevent certain ambiguities? Your answer is the latter.
Right. To avoid ambiguity with other breaky contexts, we let the innermost breaky context determine the allowable break modes.
Speaking of ambiguities, should this be illegal, even though under your rules it happens to be unambiguous? Or is it just a puzzler we tolerate? e-switch { LABEL: s-switch { { int LABEL = 2; break LABEL; } } }
It could be allowed (since you can't break-e from the switch), but it seems safer to call it a compile error. After all, you can always alpha-rename the label.
Also the other way: LABEL: s-switch { e-switch { int LABEL = 2; break LABEL; } } You want "break LABEL" to be immediately recognized as either a break-l or a break-e. The above cases seem to make it hard to do so. We could declare such code pathological and demand a relabel in either case, just as we declare local variable shadowing pathological in most cases, demanding a renaming of one of the variables. Local variable shadowing is more likely to occur than label shadowing, given that labels are a rare construct, so maybe we just let the above be a puzzler, rather than add a rule.
Or, make it the same rule. If in "break x", x could resolve as either a label or an expression, call it an ambiguity. (In either case, depending on whether you rename the variable or the label, you could then get a different error, which is "we don't serve that kind of break round these parts.") But I think its the same game either way.