`AvailabilityRange` is now being used as a currency type in more of the
compiler, and some of those uses are in permanent `ASTContext` allocations. The
class wraps the `VersionRange` utility, which is itself a wrapper around
`llvm::VersionTuple` with some additional storage for representing sentinel
values. Even though the two sentinel values can be be represented with just a
single bit of additional storage on top of the 16 bytes required to represent
`VersionTuple`, because of alignment requirements the sentinel values end up
bloating the layout of `VersionRange` by many bytes.
To make `AvailabilityRange` and `VersionRange` more efficient to store, we can
instead reserve two unlikely `llvm::VersionTuple` bit patterns as the sentinel
values instead. The values chosen are the same ones LLVM uses to represent
version tuple tombstones and empty keys in a `DenseMap`.
Introduce a constructor that takes an `llvm::VersionTuple` directly, instead of
needing to spell out `VersionRange::allGTE(<tuple>)` which is unnecessarily
verbose.
Now that `AvailabilityContext` supports multiple unavailable domains, it's no
longer necessary to have a total ordering amongst the Swift,
PackageDescription, and Embedded availability domains.
One to get the active domain for the compilation target and another to get the
ABI compatibility domain for a given domain. The ABI compatibility domain will
be needed for queries that compute whether an unavailable declaration is still
reachable at runtime.
NFC.
This operation describes the partial ordering with which Availability domains
form a lattice.
As a temporary measure, a containment ordering needs to be specified for the
Swift language, Embedded, and Package Description domains. Without this
ordering, there won't be a way for AvailabilityContext to preserve the
invariant that the unavailable domain of a child context contains the
unavailable domain for the parent. However, once AvailabilityContext is
refactored to represent the status of multiple availability domains
simultaneously, the ordering of these domains relative to each other can be
relaxed.
NFC.
Rather than exposing an `addFile` member on
ModuleDecl, have the `create` members take a
lambda that populates the files for the module.
Once module construction has finished, the files
are immutable.
Today ParenType is used:
1. As the type of ParenExpr
2. As the payload type of an unlabeled single
associated value enum case (and the type of
ParenPattern).
3. As the type for an `(X)` TypeRepr
For 1, this leads to some odd behavior, e.g the
type of `(5.0 * 5).squareRoot()` is `(Double)`. For
2, we should be checking the arity of the enum case
constructor parameters and the presence of
ParenPattern respectively. Eventually we ought to
consider replacing Paren/TuplePattern with a
PatternList node, similar to ArgumentList.
3 is one case where it could be argued that there's
some utility in preserving the sugar of the type
that the user wrote. However it's really not clear
to me that this is particularly desirable since a
bunch of diagnostic logic is already stripping
ParenTypes. In cases where we care about how the
type was written in source, we really ought to be
consulting the TypeRepr.
The "buffer ID" in a SourceFile, which is used to find the source file's
contents in the SourceManager, has always been optional. However, the
effectively every SourceFile actually does have a buffer ID, and the
vast majority of accesses to this information dereference the optional
without checking.
Update the handful of call sites that provided `nullopt` as the buffer
ID to provide a proper buffer instead. These were mostly unit tests
and testing programs, with a few places that passed a never-empty
optional through to the SourceFile constructor.
Then, remove optionality from the representation and accessors. It is
now the case that every SourceFile has a buffer ID, simplying a bunch
of code.
Some requirement machine work
Rename requirement to Value
Rename more things to Value
Fix integer checking for requirement
some docs and parser changes
Minor fixes
Previously, 'IntroducerLoc' and 'ThePattern' were only used for pattern
binidng cases. Create a new 'ConditionalPatternBindingInfo' type to
cover such cases, and make 'StmtConditionElement' a pure 'PointerUnion'
type.
This makes it clear which fields are used in which condition kind. Also,
we can expect overall size reduction of StmtCondition when the
majority of the conditions are simple boolean expressions.
Reformatting everything now that we have `llvm` namespaces. I've
separated this from the main commit to help manage merge-conflicts and
for making it a bit easier to read the mega-patch.
This is phase-1 of switching from llvm::Optional to std::optional in the
next rebranch. llvm::Optional was removed from upstream LLVM, so we need
to migrate off rather soon. On Darwin, std::optional, and llvm::Optional
have the same layout, so we don't need to be as concerned about ABI
beyond the name mangling. `llvm::Optional` is only returned from one
function in
```
getStandardTypeSubst(StringRef TypeName,
bool allowConcurrencyManglings);
```
It's the return value, so it should not impact the mangling of the
function, and the layout is the same as `std::optional`, so it should be
mostly okay. This function doesn't appear to have users, and the ABI was
already broken 2 years ago for concurrency and no one seemed to notice
so this should be "okay".
I'm doing the migration incrementally so that folks working on main can
cherry-pick back to the release/5.9 branch. Once 5.9 is done and locked
away, then we can go through and finish the replacement. Since `None`
and `Optional` show up in contexts where they are not `llvm::None` and
`llvm::Optional`, I'm preparing the work now by going through and
removing the namespace unwrapping and making the `llvm` namespace
explicit. This should make it fairly mechanical to go through and
replace llvm::Optional with std::optional, and llvm::None with
std::nullopt. It's also a change that can be brought onto the
release/5.9 with minimal impact. This should be an NFC change.
In the Swift grammar, the top-level of a source file is a mix of three
different kinds of "items": declarations, statements, and expressions.
However, the existing parser forces all of these into declarations at
parse time, wrapping statements and expressions in TopLevelCodeDecls,
so the primary API for getting the top-level entities in source files
is based on getting declarations.
Start generalizing the representation by storing ASTNode instances at
the top level, rather than declaration pointers, updating many (but
not all!) uses of this API. The walk over declarations is a (cached)
filter to pick out all of the declarations. Existing parsed files are
unaffected (the parser still creates top-level code declarations), but
the new "macro expansion" source file kind skips creating top-level
code declarations so we get the pure parse tree. Additionally, some
generalized clients (like ASTScope lookup) will now look at the list
of items, so they'll be able to walk into statements and expressions
without the intervening TopLevelCodeDecl.
Over time, I'd like to phase out `getTopLevelDecls()` entirely,
relying on the new `getTopLevelItems()` for parsed content. We can
introduce TopLevelCodeDecls more lazily for semantic walks.
These will never appear in the source language, but can arise
after substitution when the original type is a tuple type with
a pack expansion type.
Two examples:
- original type: (Int, T...), substitution T := {}
- original type: (T...), substitution T := {Int}
We need to model these correctly to maintain invariants.
Callers that previously used to rely on TupleType::get()
returning a ParenType now explicitly check for the one-element
case instead.