The `@differentiable` attribute marks a function as differentiable.
Example:
```
@differentiable(wrt: x, jvp: derivativeFoo where T: Differentiable)
func id<T>(_ x: T) -> T { x }
```
The `@differentiable` attribute has an optional `wrt:` clause specifying the
parameters that are differentiated "with respect to", i.e. the differentiability
parameters. The differentiability parameters must conform to the
`Differentiable` protocol.
If the `wrt:` clause is unspecified, the differentiability parameters are
currently inferred to be all parameters that conform to `Differentiable`.
The `@differentiable` attribute also has optional `jvp:` and `vjp:` labels
for registering derivative functions. These labels are deprecated in favor of
the `@derivative` attribute and will be removed soon.
The `@differentiable` attribute also has an optional `where` clause, specifying
extra differentiability requirements for generic functions.
The `@differentiable` attribute is gated by the
`-enable-experimental-differentiable-programming` flag.
Code changes:
- Add `DifferentiableAttributeTypeCheckRequest`.
- Currently, the request returns differentiability parameter indices, while
also resolving `JVPFunction`, `VJPFunction`, and
`DerivativeGenericSignature` and mutating them in-place in
`DifferentiableAttr`. This was the simplest approach that worked without
introducing request cycles.
- Add "is type-checked" bit to `DifferentiableAttr`.
- Alternatively, I tried changing `DifferentiableAttributeTypeCheckRequest` to
use `CacheKind::Cache` instead of `CacheKind::SeparatelyCached`, but it did
not seem to work: `@differentiable` attributes in non-primary-files were
left unchecked.
Type-checking rules (summary):
- `@differentiable` attribute must be declared on a function-like "original"
declaration: `func`, `init`, `subscript`, `var` (computed properties only).
- Parsed differentiability parameters must be valid (if they exist).
- Parsed `where` clause must be valid (if it exists).
- Differentiability parameters must all conform to `Differentiable`.
- Original result must all conform to `Differentiable`.
- If JVP/VJP functions are specified, they must match the expected type.
- `@differentiable(jvp:vjp:)` for derivative registration is deprecated in
favor of `@derivative` attribute, and will be removed soon.
- Duplicate `@differentiable` attributes with the same differentiability
parameters are invalid.
- For protocol requirements and class members with `@differentiable` attribute,
conforming types and subclasses must have the same `@differentiable` attribute
(or one with a superset of differentiability parameter indices) on
implementing/overriding declarations.
`TangentSpace` represents the tangent space of a type.
- For `Differentiable`-conforming types:
- The tangent space is the `TangentVector` associated type.
- For tuple types:
- The tangent space is a tuple of the elements' tangent space types, for the
elements that have a tangent space.
- Other types have no tangent space.
`TypeBase::getAutoDiffTangentSpace` gets the tangent space of a type.
`TangentSpace` is used to:
- Compute the derivative function type of a given original function type.
- Compute the type of tangent/adjoint values during automatic differentiation.
Progress towards TF-828: upstream `@differentiable` attribute type-checking.
Compatibility with earlier swift runtimes would require modifying the
runtime compatibility libraries to adjust the behavior of
checkMetadataState by way of typeForMangledNode or even
typeForMangledName. For now, simply require that a version of swift
whose runtime knows about prespecialized metadata is being targeted.
Introduce a new kind of constraint, the "value witness" constraint,
which captures a reference to a witness for a specific protocol
conformance. It otherwise acts like a more restricted form of a "value
member" constraint, where the specific member is known (as a
ValueDecl*) in advance.
The constraint is effectively dependent on the protocol
conformance itself; if that conformance fails, mark the type variables
in the resolved member type as "holes", so that the conformance
failure does not cascade.
Note that the resolved overload for this constraint always refers to
the requirement, rather than the witness, so we will end up recording
witness-method references in the AST rather than concrete references,
and leave it up to the optimizers to perform devirtualization. This is
demonstrated by the SIL changes needed in tests, and is part of the
wider resilience issue with conformances described by
rdar://problem/22708391.
The `@derivative` attribute registers a function as a derivative of another
function-like declaration: a `func`, `init`, `subscript`, or `var` computed
property declaration.
The `@derivative` attribute also has an optional `wrt:` clause specifying the
parameters that are differentiated "with respect to", i.e. the differentiation
parameters. The differentiation parameters must conform to the `Differentiable`
protocol.
If the `wrt:` clause is unspecified, the differentiation parameters are inferred
to be all parameters that conform to `Differentiable`.
`@derivative` attribute type-checking verifies that the type of the derivative
function declaration is consistent with the type of the referenced original
declaration and the differentiation parameters.
The `@derivative` attribute is gated by the
`-enable-experimental-differentiable-programming` flag.
Resolves TF-829.
Note: The change in ASTBuilder::createFunctionType is functionally minor,
but we need the FunctionType::Params computed _before_ the ExtInfo, so we
need to shuffle a bunch of code around.
The ExistentialSpecializer incorrectly assumed that an existential's conformances match an opened archetype. They don't. Opened archetypes strip inherited conformances per the ABI for generic argument passing. Existential values retain those inherited conformances (for some inexplicable reason).
- Rename ASTContext::getExistentialSignature() to
getOpenedArchetypeSiganture() because it was doing exactly the wrong
thing for existentials.
- Fix ConcreteExistentialInfo to produce the correct SubstitutionMap.
- Fix ExistentialSpecializer to generate the correct conformances for
init_existential by adding a collectExistentialConformances() helper.
Fixes <rdar://problem/57025861> "Assertion failed: (conformances.size() == numConformanceRequirements)" in ExistentialSpecializer on inlined code
use getTypeByMangledName when abstract metadata state is requested
This can significantly reduce the code size of apps constructing deeply
nested types with conditional conformances.
Requires a new runtime.
rdar://57157619
This bit has historically survived typechecking and parsing across source files. Stick it where we stick the other global state.
This also means we don't have to thread TopLevelContext around anymore when invoking high-level typechecking entrypoints.
This used to be a lot more relevant a long time ago when typeCheckFunctionsAndExternalDecls actually did type check external functions defined in C. Now, it serves no purpose.
The validation order change from just type checking these things eagerly doesn't seem to affect anything.
This commit moves the getNSObjectType and
getObjCSelectorType methods from TypeChecker
onto ASTContext. In addition, it moves the
FOR_KNOWN_FOUNDATION_TYPES macro into a separate
file to define each of the Obj-C type decls
we want to have access to.
`AutoDiffIndexSubset` is a fixed-size bit vector that is used for efficiently representing a subset of indices in automatic differentiation, specifically for representing a subset of parameters and results of a function to differentiate with respect to. It is uniqued in `ASTContext`.
This patch adds definition and unit tests for `AutoDiffIndexSubset` along with new files `AutoDiff.h` and `AutoDiff.cpp` into the 'AST' target, with no changes to the compiler's behavior. More data structures used for AutoDiff will be added to these files.
----------------------------
This is part of the ongoing effort to merge the experimental [differentiable programming feature](https://forums.swift.org/t/differentiable-programming-mega-proposal/28547) (informally referred to as "AutoDiff") to the 'master' branch for code reviews and better maintenance.
Upstreaming task: [TF-879](https://bugs.swift.org/browse/TF-879)
Structurally prevent a number of common anti-patterns involving generic
signatures by separating the interface into GenericSignature and the
implementation into GenericSignatureBase. In particular, this allows
the comparison operators to be deleted which forces callers to
canonicalize the signature or ask to compare pointers explicitly.
This removes it from the AST and largely replaces it with AnyObject
at the SIL and IRGen layers. Some notes:
- Reflection still uses the notion of "unknown object" to mean an
object with unknown refcounting. There's no real reason to make
this different from AnyObject (an existential containing a
single object with unknown refcounting), but this way nothing
changes for clients of Reflection, and it's consistent with how
native objects are represented.
- The value witness table and reflection descriptor for AnyObject
use the mangling "BO" instead of "yXl".
- The demangler and remangler continue to support "BO" because it's
still in use as a type encoding, even if it's not an AST-level
Type anymore.
- Type-based alias analysis for Builtin.UnknownObject was incorrect,
so it's a good thing we weren't using it.
- Same with enum layout. (This one assumed UnknownObject never
referred to an Objective-C tagged pointer. That certainly wasn't how
we were using it!)
This eliminates the entire 'lazy generic environment' concept;
essentially, all generic environments are now lazy, and since
each signature has exactly one environment, their construction
no longer needs to be co-ordinated with deserialization.
Lazy parsing for the members of nominal types and extensions depends
only on information already present in
`IterableDeclContext`. Eliminate the use of PersistentParserState as
an intermediary and have the member-parsing request construct a new
`Parser` instance itself to handle parsing. Make this possible even
for ill-formed nominal types/extensions to simplify the code path.
Eliminate `LazyMemberParser` and all of its uses, because it was only
present for lazy member parsing, which no longer needs it.
Ensure that lazy parsing of the members of nominal type definitions
and extensions is handled through a request. Most of the effort here
is in establishing a new request zone for parser requests.
To properly delay parsing type and extension bodies we need to know
which ones might contain nested operator and class definitions, since
they must be known upfront when building the global operator lookup
and AnyObject dispatch lookup tables, respectively.
To guess if the type contains operator definitions, we look for the
'func' keyword followed by an operator token.
To guess if the type contains class definitions, we look for the
'class' keyword.
For now, this information is recorded but not used. Subsequent commits
will make use of this information to delay parsing in more cases.
Traditionally a serialized binary Swift module (as used in debug info)
can only be imported if all of its Clang dependencies can be imported
*from source*.
- Swift's ClangImporter imports Clang modules by converting Clang AST
types into Swift AST types.
- LLDB knows how to find Clang types in DWARF or other debug info and
can synthesize a Clang AST from that information.
This patch introduces a DWARFImporter delegate that is implemented by
LLDB to connect these two components. With this, a Clang type can be
found (by name) in the debug info and handed over to ClangImporter to
create a Swift type from it. This path has lower fidelity than
importing the Clang modules from source, since it is missing out on
Swiftication annotations and other metadata that is not serialized in
DWARF, but it's invaluable as a fallback mechanism for the debugger
when source code for the Clang modules isn't available or the modules
are otherwise not buildable.
rdar://problem/49233932