From 75207cbe236a77b470a7f507b57739d79996d736 Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Wed, 29 Jul 2020 12:03:20 -0700 Subject: [PATCH] Allow Deriving Type Witnesses Across Files A recent change to witness matching in #32578 suddenly made the following construction illegal: // File1.swift enum MyEnumInAnotherFile { /**/ } // File2.swift extension MyEnumInAnotherFile { static var allCases: [MyEnumInAnotherFile] { /**/ } } Because it was no longer possible to derive the type witness for `AllCases`. This is because, when inference ran before synthesis, we would use the value witness to pick out the type witness and thus had no need for synthesis. Now that we run synthesis first, we ought to just allow deriving type witnesses across files, but still ban deriving value witnesses. In general, if you can utter a type in a different file to extend it, you should be able to see the requirements necessary to derive a default type witness. rdar://66279278, rdar://66279375, rdar://66279384, rdar://66279415, rdar://66279503 --- lib/Sema/DerivedConformanceCaseIterable.cpp | 3 --- lib/Sema/DerivedConformanceDifferentiable.cpp | 3 --- .../Inputs/class_differentiable_other_module.swift | 4 ++-- .../Inputs/struct_differentiable_other_module.swift | 4 ++-- .../Sema/DerivedConformances/class_differentiable.swift | 6 ++---- .../Sema/DerivedConformances/struct_differentiable.swift | 6 ++---- test/Sema/Inputs/enum_conformance_synthesis_other.swift | 4 ++++ test/Sema/enum_conformance_synthesis.swift | 7 ++++++- 8 files changed, 18 insertions(+), 19 deletions(-) diff --git a/lib/Sema/DerivedConformanceCaseIterable.cpp b/lib/Sema/DerivedConformanceCaseIterable.cpp index 19dee6674aa28..bc809b4e53930 100644 --- a/lib/Sema/DerivedConformanceCaseIterable.cpp +++ b/lib/Sema/DerivedConformanceCaseIterable.cpp @@ -113,9 +113,6 @@ ValueDecl *DerivedConformance::deriveCaseIterable(ValueDecl *requirement) { } Type DerivedConformance::deriveCaseIterable(AssociatedTypeDecl *assocType) { - if (checkAndDiagnoseDisallowedContext(assocType)) - return nullptr; - // Check that we can actually derive CaseIterable for this type. if (!canDeriveConformance(Nominal)) return nullptr; diff --git a/lib/Sema/DerivedConformanceDifferentiable.cpp b/lib/Sema/DerivedConformanceDifferentiable.cpp index 51a7ea9b77d57..8b9c3fb42b230 100644 --- a/lib/Sema/DerivedConformanceDifferentiable.cpp +++ b/lib/Sema/DerivedConformanceDifferentiable.cpp @@ -895,9 +895,6 @@ DerivedConformance::deriveDifferentiable(AssociatedTypeDecl *requirement) { diag::broken_differentiable_requirement); return std::make_pair(nullptr, nullptr); } - // Diagnose conformances in disallowed contexts. - if (checkAndDiagnoseDisallowedContext(requirement)) - return std::make_pair(nullptr, nullptr); // Start an error diagnostic before attempting derivation. // If derivation succeeds, cancel the diagnostic. diff --git a/test/AutoDiff/Sema/DerivedConformances/Inputs/class_differentiable_other_module.swift b/test/AutoDiff/Sema/DerivedConformances/Inputs/class_differentiable_other_module.swift index 99435939c4df1..15cfbf3a5ec63 100644 --- a/test/AutoDiff/Sema/DerivedConformances/Inputs/class_differentiable_other_module.swift +++ b/test/AutoDiff/Sema/DerivedConformances/Inputs/class_differentiable_other_module.swift @@ -1,9 +1,9 @@ import _Differentiation -// expected-note @+1 {{type declared here}} +// expected-note @+1 2 {{type declared here}} class OtherFileNonconforming {} -// expected-note @+1 {{type declared here}} +// expected-note @+1 2 {{type declared here}} class GenericOtherFileNonconforming { var x: T } diff --git a/test/AutoDiff/Sema/DerivedConformances/Inputs/struct_differentiable_other_module.swift b/test/AutoDiff/Sema/DerivedConformances/Inputs/struct_differentiable_other_module.swift index c3699349d3404..267eb6ef00992 100644 --- a/test/AutoDiff/Sema/DerivedConformances/Inputs/struct_differentiable_other_module.swift +++ b/test/AutoDiff/Sema/DerivedConformances/Inputs/struct_differentiable_other_module.swift @@ -1,9 +1,9 @@ import _Differentiation -// expected-note @+1 {{type declared here}} +// expected-note @+1 2 {{type declared here}} struct OtherFileNonconforming {} -// expected-note @+1 {{type declared here}} +// expected-note @+1 2 {{type declared here}} struct GenericOtherFileNonconforming { var x: T } diff --git a/test/AutoDiff/Sema/DerivedConformances/class_differentiable.swift b/test/AutoDiff/Sema/DerivedConformances/class_differentiable.swift index 220aba234b60f..4b1110b39636e 100644 --- a/test/AutoDiff/Sema/DerivedConformances/class_differentiable.swift +++ b/test/AutoDiff/Sema/DerivedConformances/class_differentiable.swift @@ -570,10 +570,8 @@ class WrappedProperties: Differentiable { // Test derived conformances in disallowed contexts. -// 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}} +// expected-error @+1 2 {{implementation of 'Differentiable' cannot be automatically synthesized in an extension in a different file to the type}} extension OtherFileNonconforming: Differentiable {} -// expected-error @+2 {{type 'GenericOtherFileNonconforming' 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}} +// expected-error @+1 2 {{implementation of 'Differentiable' cannot be automatically synthesized in an extension in a different file to the type}} extension GenericOtherFileNonconforming: Differentiable {} diff --git a/test/AutoDiff/Sema/DerivedConformances/struct_differentiable.swift b/test/AutoDiff/Sema/DerivedConformances/struct_differentiable.swift index 9da7d49f7c9de..02f9154426cf4 100644 --- a/test/AutoDiff/Sema/DerivedConformances/struct_differentiable.swift +++ b/test/AutoDiff/Sema/DerivedConformances/struct_differentiable.swift @@ -383,10 +383,8 @@ struct WrappedProperties: Differentiable { // 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}} +// expected-error @+1 2 {{implementation of 'Differentiable' cannot be automatically synthesized in an extension in a different file to the type}} extension OtherFileNonconforming: Differentiable {} -// expected-error @+2 {{type 'GenericOtherFileNonconforming' 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}} +// expected-error @+1 2 {{implementation of 'Differentiable' cannot be automatically synthesized in an extension in a different file to the type}} extension GenericOtherFileNonconforming: Differentiable {} diff --git a/test/Sema/Inputs/enum_conformance_synthesis_other.swift b/test/Sema/Inputs/enum_conformance_synthesis_other.swift index a8c67dc221b4f..275d8a9de78cb 100644 --- a/test/Sema/Inputs/enum_conformance_synthesis_other.swift +++ b/test/Sema/Inputs/enum_conformance_synthesis_other.swift @@ -29,3 +29,7 @@ extension ImpliedMain: ImplierMain {} enum ImpliedOther: ImplierOther { case a(Int) } + +enum CaseIterableAcrossFiles { + case A +} diff --git a/test/Sema/enum_conformance_synthesis.swift b/test/Sema/enum_conformance_synthesis.swift index 189d00a3851c6..494d1b3480b32 100644 --- a/test/Sema/enum_conformance_synthesis.swift +++ b/test/Sema/enum_conformance_synthesis.swift @@ -224,7 +224,12 @@ enum Complex2 { } extension Complex2 : Hashable {} extension Complex2 : CaseIterable {} // expected-error {{type 'Complex2' does not conform to protocol 'CaseIterable'}} -extension FromOtherFile: CaseIterable {} // expected-error {{cannot be automatically synthesized in an extension in a different file to the type}} expected-error {{does not conform to protocol 'CaseIterable'}} +extension FromOtherFile: CaseIterable {} // expected-error {{cannot be automatically synthesized in an extension in a different file to the type}} +extension CaseIterableAcrossFiles: CaseIterable { + public static var allCases: [CaseIterableAcrossFiles] { + return [ .A ] + } +} // No explicit conformance and it cannot be derived. enum NotExplicitlyHashableAndCannotDerive {