Move the validation of scoped imports into a
request, and force the request when we're
type-checking a primary file. This has the nice
bonus of no longer running the validation for
secondary files.
The use of `ModuleDecl::getTopLevelModule` also
allows us to correctly retrieve the top-level
module for a Clang submodule, rather than
potentially retrieving the Swift module in a mixed
source project.
Resolves SR-12265.
When extracting substitutions during type lowering, we can't discard protocol constraints
in positions where the substitution is for a nominal type's generic arguments, since associated
types on that protocol may affect the nominal type's ABI.
With the substituted function type syntax, it's easy to end up with multiple angle brackets,
so we should handle token splitting to parse things like `Optional<<A> in (A) -> () for <Int>>`
the expected way.
Semantically, an `inout` parameter is both a parameter and a result.
`@differentiable` and `@derivative` attributes now support original functions
with one "semantic result": either a formal result or an `inout` parameter.
Derivative typing rules for functions with `inout` parameters are now defined.
The differential/pullback type of a function with `inout` differentiability
parameters also has `inout` parameters. This is ideal for performance.
Differential typing rules:
- Case 1: original function has no `inout` parameters.
- Original: `(T0, T1, ...) -> R`
- Differential: `(T0.Tan, T1.Tan, ...) -> R.Tan`
- Case 2: original function has a non-wrt `inout` parameter.
- Original: `(T0, inout T1, ...) -> Void`
- Differential: `(T0.Tan, ...) -> T1.Tan`
- Case 3: original function has a wrt `inout` parameter.
- Original: `(T0, inout T1, ...) -> Void`
- Differential: `(T0.Tan, inout T1.Tan, ...) -> Void`
Pullback typing rules:
- Case 1: original function has no `inout` parameters.
- Original: `(T0, T1, ...) -> R`
- Pullback: `R.Tan -> (T0.Tan, T1.Tan, ...)`
- Case 2: original function has a non-wrt `inout` parameter.
- Original: `(T0, inout T1, ...) -> Void`
- Pullback: `(T1.Tan) -> (T0.Tan, ...)`
- Case 3: original function has a wrt `inout` parameter.
- Original: `(T0, inout T1, ...) -> Void`
- Pullback: `(inout T1.Tan) -> (T0.Tan, ...)`
Resolves TF-1164.
Using `DenseMap<SILAutoDiffDerivativeFunctionKey, ...>` in a file that includes
AutoDiff.h but not Types.h produced the following error:
```
error: invalid application of 'alignof' to an incomplete type 'swift::SILFunctionType'
```
Fix the error by:
- Including TypeAlignments.h in AutoDiff.h.
- Adding an alignment forward declaration for `SILFunctionType` to TypeAlignments.h.
- Support `@differentiable` and `@derivative` attributes for original
initializers in final classes. Reject original initializers in non-final
classes.
- Synchronize tests.
Previously, `@derivative` attribute type-checking produced a confusing error
referencing unbound types `T` and `U`:
```
'@derivative(of:)' attribute requires function to return a two-element tuple of
type '(value: T..., pullback: (U.TangentVector) -> T.TangentVector...)' or
'(value: T..., differential: (T.TangentVector...) -> U.TangentVector)'
```
Now, the error is less confusing:
```
'@derivative(of:)' attribute requires function to return a two-element tuple;
first element must have label 'value:' and second element must have label
'pullback:' or 'differential:'
```
These are mostly harmless, except that they make the two module names synonymous in qualified lookup. A hard error seems too aggressive for something that could easily be caused by uncoordinated changes to two modules, so warn instead.
This commit refactors NameBinding.cpp virtually to the point of a rewrite. The goal is to make the import handling code process a struct containing information extracted from an ImportDecl, rather than the ImportDecl itself, so that a future commit can perform the same processing on imports that are not directly represented by an ImportDecl. The result takes more code, but it disentangles a knot of complicated logic into separate threads.
One semi-functional change is that validation of scoped imports (i.e. checking that the declaration actually exists) is now deferred until all of the file’s imports have been processed. Once cross-imports are supported, this will be necessary because scoped imports can select declarations from cross-import overlays, and the full set of cross-import overlays can’t be known until all imports have been seen.
Some comments refer to things that won’t exist until the next commit, like the visibleModules property. I’ll let you in on a litlte secret: I didn’t really do this all in one go.
When a “separately imported overlay” is added to a SourceFile, two things happen:
1. The direct import of the underlying module is removed from getImports*() by default. It is only visible if the caller passes ImportFilterKind:: ShadowedBySeparateOverlay. This means that non-module-scoped lookups will search _OverlayModule before searching its re-export UnderlyingModule, allowing it to shadow underlying declarations.
2. When you ask for lookupInModule() to look in the underlying module in that source file, it looks in the overlays instead. This means that UnderlyingModule.foo() can find declarations in _OverlayModule.