Skip to content

[AutoDiff] Change TangentVector memberwise initializer access level. #28908

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions lib/Sema/CodeSynthesis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,33 @@ ConstructorDecl *swift::createMemberwiseImplicitConstructor(
ctx);
}

// SWIFT_ENABLE_TENSORFLOW
ConstructorDecl *swift::getOrCreateEffectiveMemberwiseInitializer(
ASTContext &ctx, NominalTypeDecl *nominal) {
// Compute the access level for the memberwise initializer: the minimum of:
// - Public, by default. This enables public nominal types to have public
// memberwise initializers.
// - The access level of each memberwise-initialized property in the nominal
// type declaration.
auto accessLevel = AccessLevel::Public;
for (auto *member : nominal->getMembers()) {
auto var = dyn_cast<VarDecl>(member);
if (!var ||
!var->isMemberwiseInitialized(/*preferDeclaredProperties=*/true))
continue;
accessLevel = std::min(accessLevel, var->getFormalAccess());
}
if (auto *initDecl = nominal->getEffectiveMemberwiseInitializer()) {
initDecl->overwriteAccess(accessLevel);
return initDecl;
}
auto *initDecl = createMemberwiseImplicitConstructor(ctx, nominal);
initDecl->overwriteAccess(accessLevel);
nominal->addMember(initDecl);
return initDecl;
}
// SWIFT_ENABLE_TENSORFLOW END

/// Create a stub body that emits a fatal error message.
static std::pair<BraceStmt *, bool>
synthesizeStubBody(AbstractFunctionDecl *fn, void *) {
Expand Down
17 changes: 17 additions & 0 deletions lib/Sema/CodeSynthesis.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,23 @@ Expr *buildArgumentForwardingExpr(ArrayRef<ParamDecl*> params,

ConstructorDecl *createMemberwiseImplicitConstructor(ASTContext &ctx,
NominalTypeDecl *decl);

// SWIFT_ENABLE_TENSORFLOW
// Get the effective memberwise initializer of the given nominal type, or create
// it if it does not exist.
// Sets the access level of the memberwise initializer to the minimum of:
// - Public, by default. This enables public nominal types to have public
// memberwise initializers.
// - NOTE(TF-1077): The `public` default is important for `TangentVector`
// structs synthesized during `Differentiable` derived conformances.
// Manually extending `TangentVector` structs to define a public
// memberwise initializer causes a redeclaration error.
// - The access level of each memberwise-initialized property in the nominal
// type declaration.
ConstructorDecl *getOrCreateEffectiveMemberwiseInitializer(
ASTContext &ctx, NominalTypeDecl *nominal);
// SWIFT_ENABLE_TENSORFLOW END

} // end namespace swift

#endif
11 changes: 0 additions & 11 deletions lib/Sema/DerivedConformanceElementaryFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,6 @@ static ValueDecl *getElementaryFunctionRequirement(
}
}

// Get the effective memberwise initializer of the given nominal type, or create
// it if it does not exist.
static ConstructorDecl *getOrCreateEffectiveMemberwiseInitializer(
ASTContext &ctx, NominalTypeDecl *nominal) {
if (auto *initDecl = nominal->getEffectiveMemberwiseInitializer())
return initDecl;
auto *initDecl = createMemberwiseImplicitConstructor(ctx, nominal);
nominal->addMember(initDecl);
return initDecl;
}

bool DerivedConformance::canDeriveElementaryFunctions(NominalTypeDecl *nominal,
DeclContext *DC) {
// Nominal type must be a struct. (Zero stored properties is okay.)
Expand Down
12 changes: 0 additions & 12 deletions lib/Sema/DerivedConformanceRingMathProtocols.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,6 @@ static ValueDecl *getProtocolRequirement(ProtocolDecl *proto, Identifier name) {
return lookup.front();
}

// Get the effective memberwise initializer of the given nominal type, or create
// it if it does not exist.
static ConstructorDecl *getOrCreateEffectiveMemberwiseInitializer(
ASTContext &ctx, NominalTypeDecl *nominal) {
if (auto *initDecl = nominal->getEffectiveMemberwiseInitializer())
return initDecl;
auto *initDecl = createMemberwiseImplicitConstructor(
ctx, nominal);
nominal->addMember(initDecl);
return initDecl;
}

// Return true if given nominal type has a `let` stored with an initial value.
// TODO: Move function to shared place for use with other derived conformances.
static bool hasLetStoredPropertyWithInitialValue(NominalTypeDecl *nominal) {
Expand Down
56 changes: 56 additions & 0 deletions test/Sema/differentiable_access_level.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// SWIFT_ENABLE_TENSORFLOW
// RUN: %target-swift-frontend -print-ast %s | %FileCheck %s

// Test `Differentiable` derived conformances.
// Verify access levels of synthesized `TangentVector` types and their memberwise initializers.
// `TangentVector` memberwise initializer access level should match `TangentVector` access level.

public struct PublicStruct: Differentiable {}
internal struct InternalStruct: Differentiable {}
private struct PrivateStruct: Differentiable {}

// CHECK-LABEL: public struct PublicStruct : Differentiable {
// CHECK: internal init()
// CHECK: public struct TangentVector : Differentiable, AdditiveArithmetic, PointwiseMultiplicative, ElementaryFunctions {
// CHECK: public init()
// CHECK: }
// CHECK: }

// CHECK-LABEL: internal struct InternalStruct : Differentiable {
// CHECK: internal init()
// CHECK: internal struct TangentVector : Differentiable, AdditiveArithmetic, PointwiseMultiplicative, ElementaryFunctions {
// CHECK: public init()
// CHECK: }
// CHECK: }

// CHECK-LABEL: private struct PrivateStruct : Differentiable {
// CHECK: internal init()
// CHECK: fileprivate struct TangentVector : Differentiable, AdditiveArithmetic, PointwiseMultiplicative, ElementaryFunctions {
// CHECK: public init()
// CHECK: }
// CHECK: }

public class PublicClass: Differentiable {}
internal class InternalClass: Differentiable {}
private class PrivateClass: Differentiable {}

// CHECK-LABEL: public class PublicClass : Differentiable {
// CHECK: internal init()
// CHECK: public struct TangentVector : Differentiable, AdditiveArithmetic, PointwiseMultiplicative, ElementaryFunctions {
// CHECK: public init()
// CHECK: }
// CHECK: }

// CHECK-LABEL: internal class InternalClass : Differentiable {
// CHECK: internal init()
// CHECK: internal struct TangentVector : Differentiable, AdditiveArithmetic, PointwiseMultiplicative, ElementaryFunctions {
// CHECK: public init()
// CHECK: }
// CHECK: }

// CHECK-LABEL: private class PrivateClass : Differentiable {
// CHECK: internal init()
// CHECK: fileprivate struct TangentVector : Differentiable, AdditiveArithmetic, PointwiseMultiplicative, ElementaryFunctions {
// CHECK: public init()
// CHECK: }
// CHECK: }
2 changes: 1 addition & 1 deletion test/Sema/struct_differentiable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ extension NoMemberwiseInitializerExtended: Differentiable
extension NoMemberwiseInitializerExtended: EuclideanDifferentiable
where T : Differentiable & AdditiveArithmetic {}

// Test derived conformances in disallowed contexts.
// Verify that cross-file derived conformances are disallowed.

// expected-error @+2 {{type 'OtherFileNonconforming' does not conform to protocol 'Differentiable'}}
// expected-error @+1 {{implementation of 'Differentiable' cannot be automatically synthesized in an extension in a different file to the type}}
Expand Down