4 ms·
> You don't need the `return` keyword in Rust, if the last expression in a function body (or any other body, we'll see more of this later) is not finished with
by leoc 13y ago
> You don't need the `return` keyword in Rust, if the last expression in a function body (or any other body, we'll see more of this later) is not finished with a semicolon, then it is the return value. So `foo` will always return "world". The `return` keyword still exists so we can do early returns. You can replace `"world"` with `return "world";` and it will have the same effect.
Is this a bit brittle for a language which is expected to have applications in safety/security-critical coding? It's not hard to imagine side-effecting last expressions with discarded return values being turned into (effective) return statements by an omitted semicolon. Maybe the type system or other bits of the language would prevent this?
- the1 13y agoyes. it'll prevent.
- pcwalton 13y agoThe type system generally prevents this, because you get a type error if the function return type is not as it's declared. More generally, it's not good Rust style to ignore return values, and dropping a type that should not be ignored (e.g. an error) causes the compiler to emit a warning.
- sdegutis 13y ago> it's not good Rust style to ignore return values, and dropping a type that should not be ignored If I remember correctly, much of OpenSSL is not written in "good C style" either. Considering that we're talking about "a language which is expected to have applications in safety/security-critical coding", it seems like a legitimate concern.
- pcwalton 13y agoI knew I would get someone calling me out on "it's not good Rust style". This style is enforced by warnings for important types, such as errors. The semicolon thing is repeatedly brought up as a possible source of errors, and I had concerns about it too at one point, but I've never seen it lead to a single one. There are just too many other safeguards. First of all, you get warnings on unused results for important types (for example, errors). Warning on dropping errors covers the hazards for crypto (and I can go into more detail here if wanted). Second, it's extremely unlikely that changing the return type from unit to something else won't cause a type error later down the line. For instance, returning a unit value from a function declared to return non-unit gives you a type error.
- kenko 13y ago> This style is enforced by warnings for important types, such as errors. How do you inform the compiler that a type is important? You might not be using the standard Result type.
- pcwalton 13y agoYou use an attribute, "#[must_use]". I haven't seen code not use the standard Result type, and I don't think it's likely. First of all, it's generic, so you aren't forced into a set of errors or an interface that you have to conform to—there's no reason not to use it. Second, there's strong pressure to use Result: all of the standard libraries use that type, so you'd have to write a lot of code to convert back and forth between your own error type and Result if you wanted to create your own for some reason. It'd also be less convenient from an import point of view: you'd always have to import your custom Result everywhere, whereas Result is always available right there in the prelude. Plus, you get really convenient "try!" macro sugar if you use Result. All of this means that you'd really have to go out of your way to not use Result, and my experience matches this.
- rcxdude 13y agoI'm not sure it's even possible to come up with a piece of code where a misplaced or missing semicolon causes a problem which isn't just a compiler error. If a semicolon is missing and there are more statements after it, the parser will complain ('foo' is not equivalent to 'return foo;' syntactically). If a semicolon is present but shouldn't be there will be a type error, unless the type without it would be (), in which case it makes no difference.
- kibwen 13y agoPrecisely. In other languages this would be a legitimate concern, and a lot of people (including myself!) immediately prickle upon learning of this feature before learning the ins and outs of the rest of the language. Fortunately, Rust's specific combination of features (most notably, that function signatures are not inferred, and must be typed explicitly) mean that I've never seen an error resulting from this in three years of using the language, and I've been unable to even contrive of an example where this could cause an error.