Does loop { } disables dropck by design?

It seems that loop { } disables drop checking of code that follows it inside a block.
I saw this pattern used here, and it turns out to be quite useful.
Is this by design and supported by the language (i.e. can I assume it will always work in future versions of Rust)?

It's a syntactic version of if false {...}. Those checkers doesn't utilize actual value of the condition even if it's hardcoded constant so they still check code inside if false{...}. But they still perform flow analysis and code after loop {} is obviously unreachable even without evaluating constants.

2 Likes

Interesting to know that the cks are smart enough to see that code after loop { } will never execute. Does this work the same for any -> ! (eg. panic!() or unreachable!())? Is it safe to assume that code that makes use of this trick will not break in the future?

That's not particularly smart. loop is by definition an infinite loop, so if there are no breaks or returns inside it, nothing after it can be reached. This is an easier analysis than, for example, fully const-evaluating the condition of an if, because the loop construct is designed to be an endless loop.

3 Likes

Well, loop { } is non terminating but loop isn't necessarily endless. It has no formal terminating condition but its body can have arbitrary conditions that will make the loop stop so while loop { } is trivial to analyse, the general case is probably not. I had used loop in conjunction with while to emulate the classical for (init-statement condition ; iteration-expression) where it is more convenient than just a while (i.e. when a iteration-expression must execute when continue is hit). I guess that borrowck/dropck would not be able to correctly deduce that such loop is endless or not.

That would have a break or return, no? The compiler can see that, and even if false { break } will stop being considered infinite. Similarly, while true {} is not considered infinite at this level.

3 Likes

I was thinking about a possible panic!() (that could be caught) inside the loop, but I'm not knowledgeable about flow analysis so it may be nonsense. The crux of my question is whether the exploitation of loop { } used in the code is supported by the language and is not subject to breaking

If a panic is caught elsewhere, that doesn't affect the local control flow, deciding whether code after the loop is reachable. And catch_unwind always introduces a function boundary too.

The important point is that only with a break will the code immediately after the loop ever be reachable. With return or panic!() control flow will exit straight out of the whole function instead. By the way, using panic!() or return should have a similar effect w.r.t. how the borrow checker treats the subsequent code. (I don’t know off the top of my head, how it is with regards to “dropck” as indicated in the code you linked to. One difference between loop {} and panic/return is that the latter two do drop local variables, whereas loop {} just stays in that loop.)

3 Likes

That is literally what I was saying:

I'm not sure what in this needs correcting.

A panic also diverges, just like an infinite loop. If the code panics, then you can not reach the subsequent instructions, either.

I was not correcting what you said and in fact agreed that loop is, by definition, non terminating as you noted in you comment.