-
Notifications
You must be signed in to change notification settings - Fork 10.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Do not generate implicit `@differentiable` attribute on protocol witness when conformance is in a different file. Gardening. Add tests.
- Loading branch information
Showing
6 changed files
with
169 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
49 changes: 49 additions & 0 deletions
49
...Diff/downstream/implicit_nonpublic_differentiable_attr_cross_file/Inputs/other_file.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
protocol Protocol: Differentiable { | ||
// expected-note @+2 {{protocol requires function 'internalMethod1' with type '(Float) -> Float'}} | ||
@differentiable(wrt: (self, x)) | ||
func internalMethod1(_ x: Float) -> Float | ||
|
||
// expected-note @+3 {{protocol requires function 'internalMethod2' with type '(Float) -> Float'}} | ||
@differentiable(wrt: (self, x)) | ||
@differentiable(wrt: x) | ||
func internalMethod2(_ x: Float) -> Float | ||
|
||
@differentiable(wrt: (self, x)) | ||
@differentiable(wrt: x) | ||
func internalMethod3(_ x: Float) -> Float | ||
} | ||
|
||
protocol Protocol2: Differentiable { | ||
@differentiable(wrt: (self, x)) | ||
func internalMethod4(_ x: Float) -> Float | ||
} | ||
|
||
// Note: | ||
// - No `ConformingStruct: Protocol` conformance exists in this file, so this | ||
// file should compile just file. | ||
// - A `ConformingStruct: Protocol` conformance in a different file should be | ||
// diagnosed to prevent linker errors. Without a diagnostic, compilation of | ||
// the other file creates external references to symbols for implicit | ||
// `@differentiable` attributes, even though no such symbols exist. | ||
// Context: https://github.com/apple/swift/pull/29771#issuecomment-585059721 | ||
|
||
struct ConformingStruct: Differentiable { | ||
// Expected: errors for missing `@differentiable` attribute. | ||
// expected-note @+1 {{candidate is missing attribute '@differentiable'}} | ||
func internalMethod1(_ x: Float) -> Float { | ||
x | ||
} | ||
|
||
// Expected: errors for missing `@differentiable` superset attribute. | ||
// expected-note @+2 {{candidate is missing attribute '@differentiable'}} | ||
@differentiable(wrt: x) | ||
func internalMethod2(_ x: Float) -> Float { | ||
x | ||
} | ||
|
||
// Expected: no errors for missing `@differentiable` subset attribute. | ||
@differentiable(wrt: (self, x)) | ||
func internalMethod3(_ x: Float) -> Float { | ||
x | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
test/AutoDiff/downstream/implicit_nonpublic_differentiable_attr_cross_file/main.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// Test missing protocol requirement `@differentiable` attribute errors for | ||
// non-public protocol witnesses, when the protocol conformance is declared in a | ||
// separate file from witnesses. | ||
// | ||
// Implicit `@differentiable` attributes cannot be generated for protocol | ||
// witnesses when the conformance is declared from a separate file from the | ||
// witness. Otherwise, compilation of the file containing the conformance | ||
// creates external references to symbols for implicit `@differentiable` | ||
// attributes, even though no such symbols exist. | ||
// | ||
// Context: https://github.com/apple/swift/pull/29771#issuecomment-585059721 | ||
|
||
// Note: `swiftc main.swift other_file.swift` runs three commands: | ||
// - `swiftc -frontend -primary-file main.swift other_file.swift -o ...` | ||
// - `swiftc -frontend main.swift -primary-file other_file.swift -o ...` | ||
// - `/usr/bin/ld ...` | ||
// | ||
// `%target-build-swift` performs `swiftc main.swift other_file.swift`, so it is expected to fail (hence `not`). | ||
// `swiftc -frontend -primary-file main.swift other_file.swift` should succeed, so no need for `-verify`. | ||
// `swiftc -frontend main.swift -primary-file other_file.swift` should fail, so `-verify` is needed. | ||
|
||
// RUN: %target-swift-frontend -c -verify -primary-file %s %S/Inputs/other_file.swift | ||
// RUN: %target-swift-frontend -c %s -primary-file %S/Inputs/other_file.swift | ||
// RUN: not %target-build-swift %s %S/Inputs/other_file.swift | ||
|
||
// Error: conformance is in different file than witnesses. | ||
// expected-error @+1 {{type 'ConformingStruct' does not conform to protocol 'Protocol'}} | ||
extension ConformingStruct: Protocol {} | ||
|
||
// No error: conformance is in same file as witnesses. | ||
extension ConformingStruct: Protocol2 { | ||
func internalMethod4(_ x: Float) -> Float { | ||
x | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
test/AutoDiff/downstream/implicit_nonpublic_differentiable_attr_sil.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// RUN: %target-swift-frontend -emit-sil -verify %s | ||
|
||
// Test end-to-end differentiation involving implicit `@differentiable` | ||
// attributes for non-public protocol witnesses. | ||
// | ||
// Specifically, test the diagnostic source locations for implicit attributes. | ||
|
||
protocol Protocol: Differentiable { | ||
// Note: error below comes from the implicit `@differentiable` attribute on | ||
// `PublicConformingStruct.internalMethod`. The source location of the | ||
// implicit attribute is copied from the protocol requirement's attribute. | ||
|
||
// expected-error @+1 {{function is not differentiable}} | ||
@differentiable(wrt: (self, x)) | ||
func internalMethod(_ x: Float) -> Float | ||
} | ||
|
||
struct ConformingStruct: Protocol { | ||
// Expected: | ||
// - No error for missing `@differentiable` attribute on internal protocol witness. | ||
// An implicit `@differentiable` attribute should be created. | ||
// - A non-differentiability error, because the method body is non-differentiable. | ||
// expected-note @+1 {{when differentiating this function definition}} | ||
func internalMethod(_ x: Float) -> Float { | ||
// expected-note @+1 {{cannot differentiate through a non-differentiable result; do you want to use 'withoutDerivative(at:)'?}} | ||
return Float(Int(x)) | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
test/AutoDiff/downstream/implicit_nonpublic_differentiable_attr_type_checking.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// RUN: %target-swift-frontend -print-ast -verify %s | %FileCheck %s | ||
|
||
// Test implicit `@differentiable` attributes for non-public protocol witnesses. | ||
|
||
protocol InternalProtocol: Differentiable { | ||
// expected-note @+3 {{protocol requires function 'publicMethod' with type '(Float) -> Float'}} | ||
@differentiable(wrt: self) | ||
@differentiable(wrt: (self, x)) | ||
func publicMethod(_ x: Float) -> Float | ||
|
||
@differentiable(wrt: self) | ||
@differentiable(wrt: (self, x)) | ||
func internalMethod(_ x: Float) -> Float | ||
} | ||
|
||
// expected-error @+1 {{type 'PublicConformingStruct' does not conform to protocol 'InternalProtocol'}} | ||
public struct PublicConformingStruct: InternalProtocol { | ||
// Expected: error for missing `@differentiable` attribute on public protocol witness. | ||
// expected-note @+1 {{candidate is missing attribute '@differentiable'}} | ||
public func publicMethod(_ x: Float) -> Float { | ||
x | ||
} | ||
|
||
// Expected: no error for missing `@differentiable` attribute on internal protocol witness. | ||
// Implicit `@differentiable` attributes should be created. | ||
func internalMethod(_ x: Float) -> Float { | ||
x | ||
} | ||
} | ||
|
||
// CHECK-LABEL: public struct PublicConformingStruct : InternalProtocol { | ||
// CHECK: public func publicMethod(_ x: Float) -> Float | ||
// CHECK: @differentiable(wrt: (self, x)) | ||
// CHECK: @differentiable(wrt: self) | ||
// CHECK: internal func internalMethod(_ x: Float) -> Float | ||
// CHECK: } |