Why are Option variants lang items?

Honestly I think that makes it worse, not better. If an annotation could mean anything, for all practical purposes, it means nothing.

Lang items feel to me like your coworker Jake who has worked on the project for so long that large chunks of documentation are replaced with "See Jake for details." "Jake says this algorithm is broken 12/12/2019." "Table generated by Jake's yield spreadsheet." "Copy files from /users/jake/scripts/entomology and run make." And Jake is still around, but he's pretty busy, he's moved on to other things, and he doesn't remember what he said in December of 2019 off the top of his head, so it's a chore to get time on his schedule to nail down exactly what it is that you're supposed to know.

Reading through std can definitely give one the feeling that there are a lot of #[jake]s.

I don't find this analogy applicable at all. It's not "see jake", it's "FYI, this is used in the compiler, and if you want to see how you can run Find Usages on the appropriate variant or method". Not to mention that there's the reference if you want a document about how, say, a for loop desugars and aren't interested in the implementation details. (Reading compiler-implementation-detail attributes on Some and into_iter are not the way to learn about for loops.)

lang_item isn't part of the language spec. Unless one is working on the compiler, I think the right thing to do is just to ignore them. (Splitting them into two lists that are functionally equivalent would not be an improvement to the compiler code.)

With option in particular, certain optimizations are guaranteed for FFI purposes. Such as Option<&T> is implemented as just a pointer where the None variant is simply the null pointer. Is that optimization guaranteed for all option-like enums, or is this another way Option is special?

No, this optimization applies to all option-shaped enums, and is guaranteed to apply to all option-shaped enums.

Is there any possibility of making a separate #[lang_item]-like attribute that doesn't have the "magic language semantics" power, only the "compiler knows this path" power? I think there is some benefit to that split, even if it's just making it more obvious that certain items are one or the other, and putting extra choice into moving to the more powerful category.

Coming from SML, I'm a bit confused: does this mean it's no longer (or at least, much harder) to do

enum Option<T> {
  None,
  Some(T)
}

? Or is this still possible but all the "magic" gets lost?

(In SML, I can always write

datatype 'a option = None | Some of 'a

But, I can't (or course) pass values of my 'a option to Basis functions that take the original definition of the type.)

@benknoble No, you can still do that. As I understood it, the main place where Option is special is that it is used in the desugaring of for loops, which is not relevant for your custom Option as it wont be the return value of Iterator::next in any case.

Note that I'm only referring to the compiler here. If they're both "list of things for which you can get a DefId", then there's nothing keeping one from being used as the opposite anyway, so to me it's not better to duplicate the macro and attribute and items and whatever. (But I'm also not on the compiler team, so you could make an MCP if you would rather it be the other way.)

I do think it's be great to have a list of all the "special" things, separated into the different categories, in the reference, however. That sounds like a great index of things to have.