@Jon_Shier
Have async top-level statements shipped yet? That's the only reason I use @main , it's the only way to get an async entry point into a simple executable.
Yes, yes it has.
Now back to the original question, @joshw
Newer compilers have a note suggesting you use -parse-as-library if the @main is intentional. Adding actionable note to @main error by etcwilde · Pull Request #59919 · apple/swift · GitHub
It's still not a great situation though, and I'm regularly getting pulled into conversations and questions on it. So, story time!
So. first, the name of the flag is confusing. You have an executable, not a library. It comes from an implementation detail in the C++ parser. There's an enum that tells the parser how it's parsing the file.
A "Library", as far as the parser is concerned, is any normal Swift code. a "Main" swift file is top-level code. -parse-as-library just forces the parser to set the main source file's SourceFileKind to Library instead of Main.
The current heuristic used looks at the number of files and their names. Any single file passed to the parser is given the "Main" SourceFileKind. If more than one file is passed to the compiler, any file with the name "main.swift" will be given the SourceFileKind of "main". It's important to note here that SwiftPM and Xcode both have different heuristics than the compiler, I'm only referring to the compiler.
Okay, so why are we in this mess in the first place? Parsing top-level code and a normal Swift file is different, and the resulting parse trees are not the same. Unfortunately, in order to know whether we have an @main attribute, we have to parse. By the time we know we have an @main, it's too late because we've already parsed incorrectly. I've considered the trade-off of tearing everything down and re-starting the parse in Library mode. The new Swift-Parser work does things differently. I'm hoping that I'll be able to fish the attribute out of the token stream before any ASTs are formed, and make that judgement early.
With the current parser, there's not really a point between the lexing and parsing where I can check before it's too late. The alternative to manually using -parse-as-library would be to tear everything down and restart the compilation when we get it wrong. It's a tradeoff. Maybe the wrong one? To balance things out a bit, I added the note to newer compilers to recommend adding -parse-as-library if the @main is intentional. That way you have some options and aren't just left in the dark.
Hopefully that helps shed some light on what is going on here.