[AutoDiff upstream] Add Differentiable protocol derived conformances. (#30671)

Add `AdditiveArithmetic` derived conformances for structs and classes, gated by
the `-enable-experimental-differentiable-programming` flag.

Structs and classes whose stored properties all conform to `Differentiable` can
derive `Differentiable`:

- `associatedtype TangentVector: Differentiable & AdditiveArithmetic`
  - Member `TangentVector` structs are synthesized whose stored properties are
    all `var` stored properties that conform to `Differentiable` and that are
    not `@noDerivative`.
- `mutating func move(along: TangentVector)`

The `@noDerivative` attribute may be declared on stored properties to opt out of
inclusion in synthesized `TangentVector` structs.

Some stored properties cannot be used in `TangentVector` struct synthesis and
are implicitly marked as `@noDerivative`, with a warning:

- `let` stored properties.
  - These cannot be updated by `mutating func move(along: TangentVector)`.
- Non-`Differentiable`-conforming stored properties.

`@noDerivative` also implies `@_semantics("autodiff.nonvarying")`, which is
relevant for differentiable activity analysis.

Add type-checking and SILGen tests.

Resolves TF-845.
This commit is contained in:
Dan Zheng
2020-03-27 06:40:04 -07:00
committed by GitHub
parent df5ba9cff4
commit bbe86e908d
27 changed files with 1871 additions and 15 deletions

View File

@@ -1369,3 +1369,21 @@ bool swift::hasLetStoredPropertyWithInitialValue(NominalTypeDecl *nominal) {
return v->isLet() && v->hasInitialValue();
});
}
void swift::addFixedLayoutAttr(NominalTypeDecl *nominal) {
auto &C = nominal->getASTContext();
// If nominal already has `@_fixed_layout`, return.
if (nominal->getAttrs().hasAttribute<FixedLayoutAttr>())
return;
auto access = nominal->getEffectiveAccess();
// If nominal does not have at least internal access, return.
if (access < AccessLevel::Internal)
return;
// If nominal is internal, it should have the `@usableFromInline` attribute.
if (access == AccessLevel::Internal &&
!nominal->getAttrs().hasAttribute<UsableFromInlineAttr>()) {
nominal->getAttrs().add(new (C) UsableFromInlineAttr(/*Implicit*/ true));
}
// Add `@_fixed_layout` to the nominal.
nominal->getAttrs().add(new (C) FixedLayoutAttr(/*Implicit*/ true));
}