When foo is enabled, the "bar" expression doesn't exist at all, so "foo" is the last expression in the function, which should be valid. But it's currently not parsed that way; without an explicit return, you get "error: expected ;, found #".
That's two consecutive expressions, which is not allowed syntactically. Conditional compilation doesn't make source text go away.
If you think about it: in order to interpret the cfg attributes, the compiler must already have parsed the code. Since the attribute may very well have been something else (eg. a lint, an attribute macro, etc.), the compiler can't possibly just remove the cfg'd-out tokens before parsing. Disabling code has to happen after parsing, which means that the whole thing, with both "branches" and attributes included, has to be syntactically valid.
As a rule of thumb is better to apply conditional compilation attributes on fns/methods rather than their bodies despite the downsides of added maintenance and seemingly duplicate code.
Ah. Yep, I definitely imagined that conditional config would actually prevent nodes from being included in the AST, but you're right, that doesn't really make sense.
...right, by "prevent nodes from being included in the AST," I meant it would prevent inclusion in any AST. It was just a case of...let's call it lingering C-preprocessor mental maladaptation.