[HN Gopher] Weird Expressions in Rust
___________________________________________________________________
Weird Expressions in Rust
Author : lukastyrychtr
Score : 133 points
Date : 2025-06-27 15:08 UTC (7 hours ago)
(HTM) web link (www.wakunguma.com)
(TXT) w3m dump (www.wakunguma.com)
| xyst wrote:
| These "weird expressions" probably get used code golf.
| steveklabnik wrote:
| Basically none of them are actually useful, or even do
| anything, it's mostly a parser stress test.
| behnamoh wrote:
| Great, now this stuff gets fed into LLM trainings and we'll see
| them in the next-gen model outputs.
|
| Seriously though, I love "abusing" programming languages in
| unexpected ways. My favorite so far is:
| https://evuez.net/posts/cursed-elixir.html. Reading this made me
| realize Elixir is literally macros all the way down, and it's a
| Lisp!
| ramon156 wrote:
| Note that for Rust devs these are also weird syntaxes. I feel
| like some people assume that an experienced dev can read these,
| but it takes a while to get what's going on.
| ChuckMcM wrote:
| Kind of like obfuscated C code I suspect.
| dathinab wrote:
| yes, but less risky (and less power full) because you often
| very fast can conclude that "whatever it does it's safe,
| sound and doesn't affect unrelated code"
| caim wrote:
| And how would you conclude that "fast"?
|
| You can have UB in "safe rust".
|
| https://github.com/Speykious/cve-rs
|
| You can even disable the Type check, trait check and borrow
| check in "safe rust"
|
| And all of this is unsound.
|
| https://users.rust-lang.org/t/i-finally-found-the-cheat-
| code...
| 01HNNWZ0MV43FF wrote:
| Yeah. I've been doing Rust for a few years and when I look at
| these I just see "Failed PR review, unreadable to humans"
| b0a04gl wrote:
| they exist because whole language built to treat expressions as
| firstclass citizens : blocks, ifs, matches, even macros as
| expressions that return values. so once you internalize that, all
| these weirdo one liners are artifacts. just artifact of a system
| where expressions compose infinitely. the syntax tree runs deeper
| than most people's habbits allow. you hit that depth and brain
| says this is wrong but compiler's allowing.
| gmueckl wrote:
| If a language that claims to be security focused is easily able
| to express constructs that human minds find barely
| comprehensible, or worse, then this is itself arguably a
| security issue: it's impossible to check the correctness of
| logic that is incomprehensible.
| PaulHoule wrote:
| It is a critique of macros. 500 lines of Common Lisp replaces
| 50,000 lines of C++ but those 500 lines make no sense at all
| the first time you see them.
| steveklabnik wrote:
| > If a language that claims to be security focused
|
| Rust does not claim to be particularly security-focused, only
| memory safe.
|
| Also, this means that you'd consider any expression-based
| language to be inherently a security problem.
| gmueckl wrote:
| "Memory safety" is an aspect of computer security. And
| security is the first listed value in rust's mission
| statement.
|
| Rust is not written as a pure expression based language.
| And as we all know very well from the experience with C and
| JS, any unexpected and weird looking code has the potential
| to hide great harm. Allowing programmers to stray too much
| from expected idioms is dangerous.
| steveklabnik wrote:
| It is an aspect, but it Rust does not promise your core
| is secure.
|
| It's not purely expression based but it is very close to
| it, there's only a few kinds of statements, the vast
| majority of things are expressions.
| keybored wrote:
| We would need an example of puzzling code that can easily
| hide (security) bugs.
|
| The submission shows weird program snippets. I don't
| think it shows weird snippets that can also easily hide
| bugs?
| pornel wrote:
| What's the threat model? If you're reviewing untrusted or
| security-critical code and it's incomprehensible, for any
| reason, then it's a reject.
|
| Syntax alone can't stop sufficiently determined fools. Lisp
| has famously simple syntax, but can easily be written in an
| incomprehensible way. Assembly languages have very
| restrictive syntax, but that doesn't make them easy to
| comprehend.
|
| Rust already has a pretty strong type system and tons of
| lints that stop more bad programs than many other languages.
| gmueckl wrote:
| Many modern language designers focus on shaping
| expressibility rather than providing the maximum possible
| flexibility because their designers learned from C, Lisp
| and other languages that made mistakes. Examples lamguages
| are Java, C#, D, Go... some arguably with more success than
| others. But language design that gave ultimate expressive
| power to the the programmer is a relic of the past.
| pornel wrote:
| ???
|
| "Expressibility" and "expressive power" are vague and
| subjective, so it's not clear what you mean.
|
| I suppose you object to orthogonality in the syntax?
| Golang and Java definitely lack it.
|
| But you also mention C in the context of "maximum
| possible flexibility"? There's barely any in there. I can
| only agree it has mistakes for others to learn from.
|
| There's hardly any commonality between the languages you
| list. C# keeps adding clever syntax sugar, while Go
| officially gave up on removing its noisiest boilerplate.
|
| D has fun stuff like UFCS, template metaprogramming,
| string mixins, lambdas -- enough to create
| "incomprehensible" code if you wanted to.
|
| You're talking about modern languages vs relics of the
| past, but all the languages you mention are older than
| Rust.
| int_19h wrote:
| "never" is an easily comprehensible concept once you start
| asking the right questions.
|
| But also, all examples in TFA are very artificial convoluted
| code. Meaning that you can write things like these just like
| you can write something like _&_ & _&_...x - but why would
| you? Actual real-world uses of this feature are all quite
| readable.
| derriz wrote:
| That sounds superficially reasonable to me and I'm all for
| regularity in programming language semantics but on thinking
| about it further, I actually think it's a design flaw.
|
| It makes no more sense to me for "return <expr>" to have a type
| than it does to make "if <expr>" or "break" or "{" or any other
| keyword to have a type. These are syntactic elements.
|
| Rust's type system is clearly inspired by Hindley-Milner and
| most languages using such a type system either don't even have
| a return keyword.
|
| Even if you disagree with this argument, this design decision
| has resulted in all these weird/confusing but absolutely
| useless code examples and there is no upside that I can see to
| this decision in terms of language ergonomics. What practical
| value is it to users to allow "return <expr>" to itself be an
| expression? That you can use such an "expression" as arguments
| to function calls with hilarious wtf consequences? It's a piece
| of syntactic sugar.
| steveklabnik wrote:
| Respectfully, "it makes no sense to me" isn't an argument. if
| and break both have types in Rust as well.
|
| > don't even have a return keyword.
|
| This is because they are not procedural languages, it has
| nothing to do with the type system.
|
| > there is no upside that I can see to this decision in terms
| of language ergonomics.
|
| There's tremendous upside! That's why lots of languages
| choose this. For example, there is no need for the ternary in
| Rust: if can just do that.
|
| > What practical value is it to users to allow "return
| <expr>" to itself be an expression?
|
| Code like this just works: let guess:
| u32 = match guess.trim().parse() { Ok(num) =>
| num, Err(_) => return, };
|
| That is, if return wasn't an expression, we'd have a type
| error: the two arms would have incompatible types.
| derriz wrote:
| See my comment above, your example only "just works" if the
| enclosing function has the appropriate return type (in this
| case none).
|
| So the syntactic element "return" is not just an expression
| - unlike other sub-expressions, it involves action at a
| distance - i.e. it must not just agree with it's context as
| part of an expression but it must agree with the enclosing
| fn signature.
| steveklabnik wrote:
| I replied over there, let's keep it to that sub-tree so
| we both don't have to duplicate comments :)
| NobodyNada wrote:
| In practice, it's quite a useful feature, because you can
| write things like this: let day_number =
| match name { "Sunday" => 0, "Monday"
| => 1, "Tuesday" => 2, "Wednesday" =>
| 3, "Thursday" => 4, "Friday" => 5,
| "Saturday" => 6, _ => return Err("invalid day")
| };
| bobbylarrybobby wrote:
| The issue with `return expr` not having a type is that you
| lose the ability to write something like
|
| let y = match option { Some(x) => x, None => return
| Err("whoops!"), };
|
| Without a type, the None branch loses the ability to unify
| with the Some branch. Now you could say that Rust should just
| only require branches' types to unify when all of them have a
| type, but the ! never type accomplishes that goal just fine.
| derriz wrote:
| I'm responding here because so many replies are making the
| same point.
|
| In your particular example, let's put your example into a
| context. Is fn foo(option: Option<i32>) ->
| i32 { let y = match option { Some(x) => x, None =>
| return Err("whoops!"), }; return 1; }
|
| well typed? It should be if we are to believe that "return
| <expr>" is an expression of type () - but, naturally, it
| causes a compilation error because the compiler
| specifically treats "return <expr>" unlike other
| expressions. So there is no improvement in regularity,
| while it admits all sorts of incomprehensible "puzzlers".
|
| I don't see why you'd lose this ability if you removed the
| claim that "return <expr>" is itself an expression.
| Most/many languages have mechanisms to allow expressions to
| affect flow control - e.g. with exceptions, yield, etc. -
| which do not these constructs (for example "throw x") to
| have a type.
|
| Rust could just as easily supported the syntax you use
| above without making "return <expr>" a tapeable expression.
| steveklabnik wrote:
| > Is ... well typed?
|
| It's not, but not due to the return, it's because you're
| trying to return a Result from a function that returns an
| i32. This works: fn foo(option:
| Option<i32>) -> Result<i32, &'static str> { let
| y = match option { Some(x) => x, None => return
| Err("whoops!"), }; return Ok(1); }
|
| > It should be if we are to believe that "return <expr>"
| is an expression of type ()
|
| It is not, it is an expression of type !. This type
| unifies with every other type, so the overall type of y
| is i32. return is not treated in a special way.
|
| > if you removed the claim that "return <expr>" is itself
| an expression
|
| This code would no longer work, because blocks that end
| in an expression evaluate to (), and so you _would_ get
| the divergent, not well typed error, because one arm is
| i32 and the other is ().
| derriz wrote:
| Sorry for the confusion - I meant to use ! and not ().
|
| "It's not, but not due to the return, it's because you're
| trying to return a Result from a function that returns an
| i32."
|
| That's exactly my point. "return <expr>" is not just an
| expression which can be typed. If you tell me the types
| of all the identifiers used, I can look at any expression
| in Rust which does not include a return, and tell you if
| it's well typed or not. If the expression includes a
| return, then I cannot tell you whether the expression is
| well-formed.
| steveklabnik wrote:
| > "return <expr>" is not just an expression which can be
| typed.
|
| Yes, it is, and it can. It has the type !, no matter the
| type of <expr>.
| derriz wrote:
| It only has type !, if the return type of the lexically
| enclosing function declaration has the same type as that
| of <expr>, otherwise it's illformed.
|
| For any expression NOT involving "return", I can write,
| for example:
|
| const Z = <expr>
|
| but I cannot if <expr> contains a return embedded
| somewhere. The existence of a "return" somewhere in an
| expression changes the character of the entire
| expression.
|
| I.e. there are two classes of "expressions". Those NOT
| containing returns (which are equivalent to the notion of
| "expression" in the languages that Rust was inspired by)
| and those containing a return somewhere in them which are
| subject to further rules about wellformedness.
|
| My point is that none of this is necessary at all - you
| don't need to provide type rules for every lexical
| feature of your language to have a language with a
| powerful expressive type system (like Rust's).
| steveklabnik wrote:
| Okay, I think we are indeed talking past each other and I
| see what you are saying here. I am not sure that I agree,
| exactly, but I appreciate your point. I'm going to have
| to think about it a bit more.
| int_19h wrote:
| You can write it just fine if `const Z` is itself nested
| inside a function definition.
|
| And this isn't really any different from variable
| references, if you think about it. If you have an
| expression (x + 1), you can only use it somewhere where
| there's an `x` in scope. Similarly, you can only use
| `return` somewhere where there's a function to return
| from in scope. Indeed, you could even make this explicit
| when designing the language! A function definition
| already introduces implicit let-definitions for all
| arguments in the body. Imagine if we redefined it such
| that it also introduces "return" as a local, i.e. given:
| fn foo(x: i32, y: i32) -> i32 { ... }
|
| the body of the function is written _as if_ it had these
| lines prepended: let x = ...; let
| y = ...; let return = ...; ...
|
| where "return" is a function that does the same thing as
| the statement. And similarly for break/continue and
| loops.
|
| The thing that actually makes these different from real
| variables is that they cannot be passed around as first-
| class values (e.g. having the function pass its "return"
| to another function that it calls). Although this could
| in fact be done, and with Rust lifetime annotations it
| would even be statically verifiable.
| efnx wrote:
| Well now we're just talking about personal preferences,
| then.
| bobbylarrybobby wrote:
| The type of return is !, not (). Meaning there are zero
| instances of this type (whereas there is one instance of
| ()). ! can coerce to any type.
|
| Also, the type of return is a separate matter from the
| type of the thing being returned. You obviously can't
| return Result from a function returning i32. The point of
| type coercion is that you can yield `return Err(...)` in
| one branch of a match and have it type check with the
| other branch(es).
| deathanatos wrote:
| We can use match to do pattern matching: let
| name = match color_code { 0 => "red", 1 =>
| "blue", 2 => "green", _ => "unknown",
| };
|
| The RHS of the `=>` has to be an expression, since we're
| assigning it to a variable. Here, you should already see one
| "useful" side-effect of what you're calling "syntactic
| elements" (I'd perhaps call them "block statements", which I
| think is closer to the spirit of what you're saying.) The
| whole `match ... {}` in the example above here is an
| expression (we assign the evaluation of it to a variable).
|
| > _What practical value is it to users to allow "return
| <expr>" to itself be an expression?_
|
| Now, what if I need to return an error? let
| name = match color_code { 0 => "red", 1 =>
| "blue", 2 => "green", _ => return
| Err("unknown color"), };
|
| The expression arms need to be the same type (or what is the
| type of `name`?). So now the type of the last branch is !.
| (Which as you hopefully learned from TFA, coerces to any
| type, here, to &str.)
|
| There's more ways this "block statements are actually
| expressions" is useful. The need not be a ternary operator /
| keyword (like C, C++, Python, JS, etc.): let
| x = if cond { a } else { b };
|
| In fact, if you're familiar with JavaScript, there I _want_
| this pattern, but it is not to be had: const
| x; // but x's value will depend on a computation: //
| This is illegal. if(foo) { x = 3; } else
| { x = 4; } // It's doable, but ugly:
| const x = (function() { if(foo) { return 3; } else { return
| 4; }})(); // (Yes, you can do this example with a
| ternary. // Imagine the if branches are a bit more
| complicated than a ternary, // e.g., like 2
| statements.)
|
| Similarly, loops can return a value, and that's a useful
| pattern sometimes: let x = loop { //
| e.g., find a value in a datastructure. Compute something.
| Etc. if all_done { break result; }
| };
|
| And blocks: let x = { // compute x;
| intermediate variables are properly scoped // &
| cleaned up at block close. // // There's also
| a slight visual benefit of "here we compute x" is //
| pretty clearly denoted. };
|
| > _Even if you disagree with this argument, this design
| decision has resulted in all these weird /confusing but
| absolutely useless code examples_
|
| I think one can cook up weird code examples in any language.
| wredcoll wrote:
| I appreciate, so much, that rust is slowly evolving into
| perl.
| dathinab wrote:
| it doesn't need to make sense on a higher abstraction level
| of logic/semantics
|
| I mean you don't see any of the nonsense in the blog post in
| any realistic PR (so they don't matter),
|
| but you would run into subtle edge case issues if some
| expressions where more special then other expressions (so
| that does matter),
|
| especially in context of macros/proc macros or partial "in-
| progress" code changes (which is also why `use` allows some
| "strange" {-brace usage or why a lot of things allow optional
| trailing `,` all of that makes auto code gen simpler).
| pornel wrote:
| This makes the language more uniform. Instead of having a
| special ternary ?: operator for if-else in expression
| position, you have one syntax everywhere.
|
| It makes generic code work without need to add exceptions for
| "syntactic elements". You can have methods like
| `map(callback)` that take a generic `fn() -> T` and pass
| through `T`. This can work uniformly for functions that do
| return values as well as for functions that just have
| `return;`. Having nothingness as a real type makes it just
| work using one set of rules for types, rather than having
| rules for real types plus exceptions for "syntactic
| elements".
| throwawaymaths wrote:
| its not just that some things you would usually think are
| control flow are expressions, its also that there are unusual
| rules around coercing the `noreturn` type.
| AIPedant wrote:
| Hmm my read is this is a slight overstatement - Rust was always
| built with the _idea_ of expressions as first class citizens,
| but practicality and performance requires expression-breaking
| keywords like "return" which don't fit neatly in an ML-ish
| language and have a few plain old hacks associated with
| implementing them (not "hack" as in lacking robustness; I mean
| theoretically /formally inelegant). Likewise there's some stuff
| (u8) which is a simple syntax quirk. But a lot of these
| return/etc oddities are because Rust is ultimately an
| imperative language with strong influence from functional
| programming.
| steveklabnik wrote:
| return is an expression in Rust, and it fits in well.
|
| There are very few statements: https://doc.rust-
| lang.org/stable/reference/statements.html
|
| and a lot of expressions: https://doc.rust-
| lang.org/stable/reference/expressions.html
| AIPedant wrote:
| We're speaking past each other since there's "expression"
| as defined in the Rust specification vs "expression" as in
| ordinary computer science, and Rust's use of return is
| certainly not an expression in the latter sense. It is
| shoehorned into being called an expression but it has no
| semantically meaningful type, it is an effect. A type is
| (carefully but somewhat arbitrarily) assigned to it, which
| is why some of those examples involving "return" are
| particularly goofy. It is not material for most programs
| since it only comes up with intentional misuse of the
| keyword. But "return" does not make sense in functional
| languages with true first-class expressions - functions
| don't _return_ values, they get _evaluated_ and the frame
| destruction / etc are all abstracted away. It makes sense
| in Rust because expressions in the CS sense of the term are
| ultimately not first class.
| steveklabnik wrote:
| I do think we're speaking past each other. I don't fully
| agree with your "CS sense of the term," as Rust _does_
| have a semantically meaningful type: !. This is all
| pretty bog-standard stuff. Rust isn 't doing anything
| weird or novel here.
| int_19h wrote:
| Pure functional languages have the equivalent of "never"
| - it's the bottom type. Indeed, the return type of
| `error` in Haskell is that, but also cases like
| predictable infinite recursion. But this semantics works
| great for cases like "return" and other forms of control
| transfer - the expression in which they appear also
| "never finishes" (but some other expression which
| contains that one as a subexpression does).
|
| Now, yes, ideally you'd have effects in the type system
| so that you can express this kind of stuff with more
| precision. But if you restrict this to stuff like
| return/break/continue where the destination is statically
| known and can be validated, you can treat those effect
| types as been there, just inferred for all expressions
| and forbidden to cross the function boundary.
|
| For exceptions specifically this trick no longer works
| because the whole point is for them to cross that
| boundary. But the amount of complexity this stuff adds to
| typing even trivial generic code is arguably too much for
| practical use (see also: checked exceptions in Java). In
| any case, in Rust you use Result types instead so those
| exceptions produce regular values. And although panics
| can be handled, they are certainly not meant to be used
| as a generic mechanism for transfer of control, so adding
| effect types for them alone is just not worth it.
| octachron wrote:
| Return (or other effects) does make sense as an
| expression in a functional language. Typically, OCaml has
| `raise Exception` which is also an expression, with the
| same type as `return` or any never returning function.
| And exceptions can also be used to implement a user-
| defined `return` function.
| missinglugnut wrote:
| Steve, I know you're an authority on the language but
| you've dismissed the point being made here without engaging
| with it.
|
| Return is a statement in the minds of most programmers, but
| an expression in the language. That was a very pragmatic
| decision that required an unintuitive implementation. As a
| result, we've got this post full of code that is valid to
| the compiler but doesn't make a lick of sense to most
| programmers reading it.
| steveklabnik wrote:
| > Return is a statement in the minds of most programmers
|
| I would take issue with this, sure, for a lot of people,
| they may be bringing assumptions over from languages
| where assignment is a statement. That doesn't make them
| correct.
|
| > required an unintuitive implementation
|
| To some people, sure. To others, it is not unintuitive.
| It's very regular, and people who get used to "everything
| is an expression" languages tend to prefer it, I've
| found.
| hansvm wrote:
| > people who get used to "everything is an expression"
| languages tend to prefer it, I've found
|
| I.e., if we bias our sample to the data points proving
| our point then our point is proven. It's like that quip
| about how every car insurance company can simultaneously
| claim "people who switched saved hundreds of dollars in
| average."
|
| I also like "everything is an expression" languages, but
| I don't think that's a fantastic argument.
| int_19h wrote:
| We've been going down this road for a long time now. E.g.
| "throw" is a (void-typed) expression in C++ already for
| similar reasons, although it doesn't go far enough
| without a proper bottom type. C# took it further and
| added the type so that you can write things like e.g. `x
| = y ?? throw new Error(...)`. There's no obvious reason
| why "return" should be conceptually different.
|
| A better question at this point, arguably, is why there
| should even be an expression/statement distinction in the
| first place. All imperative statements can be reasonably
| and sensibly represented as expressions that produce
| either () or "never". Semicolon then is just a sequencing
| operator, like comma in C++.
| efnx wrote:
| I've found rust to be an ML in C's clothing.
|
| The main difference from other MLs is the lack of higher
| kinded types, so it's difficult to express things like
| Functor, Monad, Arrow, etc
| GrantMoyer wrote:
| Haskell has `bottom`[1] (see also [2]), which acts like
| Rust's `return` from a type checking perspective.
|
| I wouldn't call using a uninhabited type for the type of a
| return expression theoretically inelegant. On the contrary, I
| find it quite pleasing.
|
| [1]: https://wiki.haskell.org/Bottom
|
| [2]: https://en.wikipedia.org/wiki/Bottom_type
| steveklabnik wrote:
| This post is missing my favorite one! fn
| evil_lincoln() { let _evil = println!("lincoln"); }
|
| What's weird about this?
|
| To understand what evil_lincoln is doing, you have to understand
| very old Rust. Here's the commit that introduced it:
| https://github.com/rust-lang/rust/commit/664b0ad3fcead4fe4d2...
| fn evil_lincoln() { let evil <- log "lincoln";
| }
|
| log was a keyword to print stuff to the screen. Hence the joke,
| https://en.wikipedia.org/wiki/Lincoln_Logs Now that log is the
| println! macro, the joke is lost.
|
| It doesn't say explicitly why this is "weird", but given some
| other comments in the file, // FIXME: Doesn't
| compile //let _x = log true == (ret 0);
|
| I am assuming that using the return value of log was buggy, and
| so this tested that you could save it in a variable. I don't
| remember the exact semantics of log, but if it's like println!,
| it returns (), which is useless, so binding it to a variable is
| something you'd never write in real code, so it's "weird" in that
| sense.
| ibotty wrote:
| What's the joke exactly? English is not my native language.
| jerf wrote:
| https://www.basicfun.com/lincoln-logs/
|
| This would be something the Boomer generation grew up with,
| and I think maybe the previous generation too. They're still
| around but they've certainly faded; they used to be Lego-
| level popular kids toys back then. They are named after
| President Lincoln, but only as a marketing tactic to use some
| of his reputation, there's no real connection.
|
| I would imagine even some native English speakers are
| learning something with this post. I haven't seen them in a
| while.
| ranguna wrote:
| Yes, but why is it evil?
| Analemma_ wrote:
| I think that part is a reference to a Futurama episode
| where a holodeck malfunction materialized several
| villains, including "Evil Lincoln".
| drfuchs wrote:
| There's a strong connection between President Lincoln and
| log cabins. He grew up in a series of log cabins, and this
| fact was widely known during his campaign.
| bennettnate5 wrote:
| > They were named after President Lincoln, but only as a
| marketing tactic
|
| > there's no real connection
|
| Funny--I always thought it was meant to be a pun on
| linkin', as in you're linkin' the logs together because
| they have those slots that fit precisely together on the
| ends.
| saghm wrote:
| I think it's both that and the popular tale of Lincoln
| having been born in a log cabin (which for some reason I
| thought I had heard wasn't actually true, but from
| looking into it now, it seems like a lot of sources say
| it is, so maybe I heard wrong?)
| saghm wrote:
| I'm a late millennial, and I'd sometimes see them as a kid
| too. I'm not sure about more recent generations, but I
| think that they might have stuck around longer than you
| might think.
| iforgotpassword wrote:
| I saw some kids in a park a few years ago in Beijing
| playing with those. First time I saw them. Didn't know
| the name until now though. :)
| rendaw wrote:
| What's the joke exactly? English is my native language.
| steveklabnik wrote:
| log "lincoln" is a reference to the toy "lincoln logs"
| mbStavola wrote:
| A dog entered a tavern and said: "I cannot see anything, I'll
| open this one!"
| hansjorg wrote:
| Tough crowd.
| nikolayasdf123 wrote:
| this is why I like Go
| timeon wrote:
| It does not have stress tests for parser?
| nemo1618 wrote:
| I wonder, what's the "weirdest" expression in Go? Here's one:
| type Foo struct{} func (Foo) Bar() { println("weird...")
| } func main() { ([...]func(){^^len(`
| `): (&Foo{}).Bar})[cap(append([]any(nil),1,2,3))]() }
| assbuttbuttass wrote:
| Makes sense to me, [...]func() is an array of functions, and
| [...]T{index: value} is uncommon but still perfectly
| comprehensible
| nemo1618 wrote:
| Many people aren't aware that you can use key: val
| declarations in arrays
| jenadine wrote:
| That's why I like Rust /s
| IshKebab wrote:
| Honestly I'm surprised how _not_ weird these are. Way less WTFy
| than Javascript, PHP, C or C++.
| dathinab wrote:
| yes but to be fair the blog is focused on unusual aspects of
| everything being an expression
|
| you still can create some more confusing things by idk.
| overloading some operators (but luckily not `=` and similar
| crazy C++ things) adding recursive macros and maybe combining
| it with lifetime variance and coercion edge cases, maybe
| sprinkle in some arcane `#[]` annotations and people with be
| very confused, more so then in the article
| IshKebab wrote:
| Yeah... I'm just saying I haven't seen anything close to
| these things:
|
| https://github.com/denysdovhan/wtfjs
|
| https://github.com/satwikkansal/wtfpython
| Thaxll wrote:
| Why assigning a variable to a function that returns nothing is
| not a compilation error?
| steveklabnik wrote:
| Which example are you referencing?
| assbuttbuttass wrote:
| There's no such thing as a "function that returns nothing" in
| Rust. Unit, written as (), is a first class value and can be
| assigned to a variable, although there's not much point
| tialaramex wrote:
| Do you mean a function which returns "nothing" in the sense
| that it does return but it has no particular value to return,
| like Vec::clear which gets rid of the _values_ but preserves
| the capacity of the container ?
|
| In Rust the return type of this function is the unit type, the
| empty tuple (). So, the variable has this type, there's no
| problem with this in Rust, even though some lesser languages
| can't handle the idea of a type this small.
|
| Or did you mean a function which never returns, like
| std::process::exit ? In Rust this function's return type is !
| the Never type, an empty type that you ordinarily can't name in
| stable Rust.
|
| Because this type is empty, a variable of this type will
| evaporate, the compiler knows that we can't bring values into
| existence if there are no values of that type, the code paths
| in which this variable exists will never be executed, so no
| need to emit machine code.
|
| In a language with generic programming like Rust this isn't an
| error, it's actually a convenience. We can write generic error
| handling code, and then for cases where there will never be an
| error our error handling code doesn't even compile, it
| evaporates entirely, yet for cases which _can_ have actual
| errors, the error handling code is emitted.
| dathinab wrote:
| assuming you mean returning () (the empty tuple/void type)
|
| because it doesn't compose well with generics, macros, proc-
| macros etc.
|
| e.g. if you have this dump way to wrap clone: `fn foo<T:
| Clone>(v: T) -> (T, T) { let new = v.clone(); (v, new) }` it
| would implicitly not work with T = (), because then `v.clone()`
| would be a "function which returns nothing".
|
| In isolation this might seem fine but if you compose
| abstractions you sooner or later run into an edge case where it
| isn't fine.
|
| And this becomes even more a problem when macros/proc-macros
| are involved.
|
| It also makes changing code easier, lets say you have something
| like `let x = foo(); dbg!(x);` and you change the return type
| it will keep compiling as long as the type implements `Debug`,
| even if you change the type to `()` (i.e. return nothing). And
| again for normal code that is a minor nit pick, but for macros,
| proc macros, generic code of sufficient complexity sooner or
| later you run into edge cases where it really matters that it's
| allowed. Not often but often enough.
|
| Lastly and most importantly assigning `()` to a variable hurts
| no one, you won't see any such code in normal PRs.
|
| So it it doesn't hurt anyone but can be quite use full in edge
| cases.
|
| Lastly linters (mainly clippy) do warn or error for some of
| this nonsensical things, depending on the lint-set you enabled.
| npalli wrote:
| yeah this is good, but now add lifetime annotations to have fun.
| steveklabnik wrote:
| Lifetimes are not expressions and therefore can't really be put
| into odd places.
| armchairhacker wrote:
| Related: https://dtolnay.github.io/rust-quiz
|
| Rust programs that give unintuitive outputs or compile errors.
| Sniffnoy wrote:
| I don't understand the one with dont(). Why does i.get() end up
| false at the end? Shouldn't it be true after having been set by
| dont()?
| LegionMammal978 wrote:
| The final line "assert!(i.get());" asserts that i.get() is
| _true_ in the end. The ! character here belongs to the assert!
| macro, not a boolean negation. (This unfortunately gets a bit
| weird-looking when you want to write sensible stuff like "if
| !matches!(x, Some(5..=10)) { ... }".)
| Sniffnoy wrote:
| Oops, I see, thanks!
| arjvik wrote:
| I figured out how return-as-a-value made sense only upon
| realizing that in the following code, fn
| funny(){ fn f(_x: ()){} f(return);
| }
|
| f() is never called because funny() returns before it gets
| called.
|
| The reason you want return to be coercible to any type is so that
| you can write something like let x: i32 = if y
| { 4 } else { return; // type !
| coerced into i32 }
|
| And you pick the return value of ! because return never actually
| produces a value that is propagated on at runtime, it immediately
| exits the function.
|
| (Note this all works even with returning a value)
| kzrdude wrote:
| Many of them are on the same theme - the theme is `return -> !`.
|
| Here's my favourite on that theme, which I was missing from the
| list: return return return return return return
| return return return 1
| wredcoll wrote:
| Is there some meanining to the number of returns?
| kzrdude wrote:
| No, it's just nonsense. Same result with fewer or more
| returns..
| pluto_modadic wrote:
| I've absolutely seen some /cursed/ rust one liners.
|
| if you extend it to the most cursed ~6 lines of code, you really
| can obfuscate what you're doing in a way that's fiendishly hard
| to debug.
| munificent wrote:
| Does anyone know _why_ `union` isn 't a reserved word in Rust?
|
| Most contextual keywords in other languages come from either:
|
| 1. Features that were added after the language was in wide use
| and can't add keywords without breaking existing code.
|
| 2. Features where the word is particularly useful elsewhere, so
| would be painful to reserve (like `get` and `set` in Dart).
|
| But neither of those seem to apply to Rust. As far as I know,
| it's always had ML-style unions, and "union" doesn't seem to be a
| particularly useful identifier otherwise.
|
| Why isn't `union` fully reserved?
| steveklabnik wrote:
| It's simply that Rust has higher standards for breaking changes
| than "probably not in wide use." In other words, that someone
| _could have_ had `let union =`... somewhere was a reason to
| make it contextual.
|
| https://rust-lang.github.io/rfcs/1444-union.html#contextual-...
| pitaj wrote:
| It's a common operation on sets, so would make `HashSet::union`
| [1] and friends less obvious, for no real benefit.
|
| [1] https://doc.rust-
| lang.org/stable/std/collections/struct.Hash...
| JoeOfTexas wrote:
| Bruh, I started learning Rust yesterday. Why do you do this to
| me. Now I don't know anything I studied.
| steveklabnik wrote:
| You don't need to know any of this. It's just a parsing stress
| test, with meaningless programs. It's fun trivia.
| xg15 wrote:
| Rust noob here.
|
| That '!' type seemed weird in the first few examples but starts
| to make sense later on.
|
| It's essentially a "pseudo type" for everything that is
| _syntactically_ an expression, but will never return anything,
| because evaluating it causes the entire statement to be canceled.
|
| Is that correct?
| Analemma_ wrote:
| Yes. If you look at steveklabnik's example with the match
| statement elsewhere in the comments, it makes sense that '!' is
| the "never" or "unreachable" type, not because the return
| expression isn't run, but because its value will never be
| assigned to a variable, since it causes an unconditional exit
| from the function.
| NobodyNada wrote:
| Yes, exactly -- it's called the Never type.
|
| It's also useful in more places than return expressions -- for
| example, you can make a function return ! to indicate that it's
| a non-returning function, which is useful for expressing, say,
| an error handler that must crash the program; or a main loop
| that must never return. It also can help the compiler generate
| more compact code when a function is known to not return.
|
| There's currently work in progress to allow you to specify ! as
| a type everywhere, not just as function returns. This is useful
| where some generic code expects a function to return a Result
| with an implementation-specified error type, since an
| infallible implementation can specify ! as the error type.
| Then, the type checker can allow the programmer to unwrap a
| Result<T, !> without checking for errors, and the optimizer can
| remove the error-checking branches from generic code:
| https://doc.rust-lang.org/std/primitive.never.html
|
| This has taken a very long time to implement, because of some
| very subtle implications on type inference that made it
| difficult to stabilize without breaking compatibility -- but
| the 2024 edition finally figured out a way to make it possible.
| int_19h wrote:
| Not necessarily the entire statement, just some outer
| expression.
|
| Which might make more sense when you remember that the only
| statements in Rust are various declarations (`let`, `type`,
| `fn` etc) and macro invocations. Everything else is an
| "expression statement", including blocks and loops. Thus you
| can do stuff like: // Compute the first
| Fibbonaci number >10 let n = { let mut x1 =
| 0; let mut x2 = 1; loop {
| let x = x1 + x2; if x > 10 { break x }
| x1 = x2; x2 = x; } };
|
| Note that `break` never leaves the let-statement here - it just
| terminates the loop expression and forces it to yield a value
| (`break` without arguments yields (), and ditto for loops
| without break).
|
| You can also break out of regular blocks if they are labelled
| and you use the labelled form of break: let x
| = 'label: { ... break 'label 42 ... }
|
| This all can very easily lead to convoluted code if not used
| sparingly, but sometimes a mutating loop with mutable data
| encapsulated within and a break to yield it once the
| computation is complete is genuinely the most straightforward
| way to write something.
| lacker wrote:
| I think there's a mistake in the explanation for
| "bathroom_stall". When describing the guard in this expression:
| if (i+=1) != (i+=1)
|
| The post says, "The if statement is always going to be false
| because the right expression will always be one more than the
| left." But it's a not-equals. The if statement is always going to
| be false because in Rust "i += 1" doesn't return an integer
| value, it returns a (). So comparing any two += statements, they
| are always equal. Since the guard is a != comparison, the if
| statement is always false.
| keybored wrote:
| Once I tried how many `{{{...}}}` I needed to make javac crash.
| It wasn't that many.
| sureglymop wrote:
| With yesterdays release let chains got released. Really needed
| feature but can sometimes look pretty cursed: https://blog.rust-
| lang.org/2025/06/26/Rust-1.88.0/#let-chain...
| bensons1 wrote:
| I am sort of amused, a memory safe language deploys this sort of
| juggling
| nfrmatk wrote:
| There's a fun RustConf talk on this topic from a few years ago.
| https://youtu.be/tNVDjMxCz-c
___________________________________________________________________
(page generated 2025-06-27 23:00 UTC)