blob: 0eb68c7911bb6892cc63f7781af0b441498facd1 [file] [log] [blame]
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend %S/Inputs/placement_module_A.swift -emit-module -parse-as-library -o %t
// RUN: %target-swift-frontend -I %t %S/Inputs/placement_module_B.swift -emit-module -parse-as-library -o %t
// RUN: %target-swift-frontend -typecheck -primary-file %s %S/Inputs/placement_2.swift -I %t -verify
// Tests for the placement of conformances as well as conflicts
// between conformances that come from different sources.
import placement_module_A
import placement_module_B
protocol P1 { }
protocol P2a : P1 { }
protocol P3a : P2a { }
protocol P2b : P1 { }
protocol P3b : P2b { }
protocol P4 : P3a, P3b { }
protocol AnyObjectRefinement : AnyObject { }
// ===========================================================================
// Tests within a single source file
// ===========================================================================
// ---------------------------------------------------------------------------
// Multiple explicit conformances to the same protocol
// ---------------------------------------------------------------------------
struct Explicit1 : P1 { } // expected-note{{'Explicit1' declares conformance to protocol 'P1' here}}
extension Explicit1 : P1 { } // expected-error{{redundant conformance of 'Explicit1' to protocol 'P1'}}
struct Explicit2 { }
extension Explicit2 : P1 { } // expected-note 2{{'Explicit2' declares conformance to protocol 'P1' here}}
extension Explicit2 : P1 { } // expected-error{{redundant conformance of 'Explicit2' to protocol 'P1'}}
extension Explicit2 : P1 { } // expected-error{{redundant conformance of 'Explicit2' to protocol 'P1'}}
// ---------------------------------------------------------------------------
// Multiple implicit conformances, with no ambiguities
// ---------------------------------------------------------------------------
struct MultipleImplicit1 : P2a { }
extension MultipleImplicit1 : P3a { }
struct MultipleImplicit2 : P4 { }
struct MultipleImplicit3 : P4 { }
extension MultipleImplicit3 : P1 { }
// ---------------------------------------------------------------------------
// Multiple implicit conformances, ambiguity resolved because they
// land in the same context.
// ---------------------------------------------------------------------------
struct MultipleImplicit4 : P2a, P2b { }
struct MultipleImplicit5 { }
extension MultipleImplicit5 : P2a, P2b { }
struct MultipleImplicit6 : P4 { }
extension MultipleImplicit6 : P3a { }
struct MultipleImplicit7 : P2a { }
extension MultipleImplicit7 : P2b { }
// ---------------------------------------------------------------------------
// Multiple implicit conformances, ambiguity resolved via explicit conformance
// ---------------------------------------------------------------------------
struct ExplicitMultipleImplicit1 : P2a { }
extension ExplicitMultipleImplicit1 : P2b { }
extension ExplicitMultipleImplicit1 : P1 { } // resolves ambiguity
// ---------------------------------------------------------------------------
// Implicit conformances superseded by inherited conformances
// ---------------------------------------------------------------------------
class ImplicitSuper1 : P3a { }
class ImplicitSub1 : ImplicitSuper1 { }
extension ImplicitSub1 : P4 { } // okay, introduces new conformance to P4; the rest are superseded
// ---------------------------------------------------------------------------
// Synthesized conformances superseded by implicit conformances
// ---------------------------------------------------------------------------
enum SuitA { case Spades, Hearts, Clubs, Diamonds }
func <(lhs: SuitA, rhs: SuitA) -> Bool { return false }
extension SuitA : Comparable {} // okay, implied conformance to Equatable here is preferred.
enum SuitB: Equatable { case Spades, Hearts, Clubs, Diamonds }
func <(lhs: SuitB, rhs: SuitB) -> Bool { return false }
extension SuitB : Comparable {} // okay, explicitly declared earlier.
enum SuitC { case Spades, Hearts, Clubs, Diamonds }
func <(lhs: SuitC, rhs: SuitC) -> Bool { return false }
extension SuitC : Equatable, Comparable {} // okay, explicitly declared here.
// ---------------------------------------------------------------------------
// Explicit conformances conflicting with inherited conformances
// ---------------------------------------------------------------------------
class ExplicitSuper1 : P3a { }
class ExplicitSub1 : ImplicitSuper1 { } // expected-note{{'ExplicitSub1' inherits conformance to protocol 'P1' from superclass here}}
extension ExplicitSub1 : P1 { } // expected-error{{redundant conformance of 'ExplicitSub1' to protocol 'P1'}}
// ---------------------------------------------------------------------------
// Suppression of synthesized conformances
// ---------------------------------------------------------------------------
class SynthesizedClass1 : AnyObject { } // expected-error{{inheritance from non-protocol, non-class type 'AnyObject'}}
class SynthesizedClass2 { }
extension SynthesizedClass2 : AnyObject { } // expected-error{{inheritance from non-protocol type 'AnyObject'}}
class SynthesizedClass3 : AnyObjectRefinement { }
class SynthesizedClass4 { }
extension SynthesizedClass4 : AnyObjectRefinement { }
class SynthesizedSubClass1 : SynthesizedClass1, AnyObject { } // expected-error{{inheritance from non-protocol, non-class type 'AnyObject'}}
class SynthesizedSubClass2 : SynthesizedClass2 { }
extension SynthesizedSubClass2 : AnyObject { } // expected-error{{inheritance from non-protocol type 'AnyObject'}}
class SynthesizedSubClass3 : SynthesizedClass1, AnyObjectRefinement { }
class SynthesizedSubClass4 : SynthesizedClass2 { }
extension SynthesizedSubClass4 : AnyObjectRefinement { }
enum SynthesizedEnum1 : Int, RawRepresentable { case none = 0 }
enum SynthesizedEnum2 : Int { case none = 0 }
extension SynthesizedEnum2 : RawRepresentable { }
// ===========================================================================
// Tests across different source files
// ===========================================================================
// ---------------------------------------------------------------------------
// Multiple explicit conformances to the same protocol
// ---------------------------------------------------------------------------
struct MFExplicit1 : P1 { }
extension MFExplicit2 : P1 { } // expected-error{{redundant conformance of 'MFExplicit2' to protocol 'P1'}}
// ---------------------------------------------------------------------------
// Multiple implicit conformances, with no ambiguities
// ---------------------------------------------------------------------------
extension MFMultipleImplicit1 : P3a { }
struct MFMultipleImplicit2 : P4 { }
extension MFMultipleImplicit3 : P1 { }
extension MFMultipleImplicit4 : P3a { }
extension MFMultipleImplicit5 : P2b { }
// ---------------------------------------------------------------------------
// Explicit conformances conflicting with inherited conformances
// ---------------------------------------------------------------------------
class MFExplicitSuper1 : P3a { }
extension MFExplicitSub1 : P1 { } // expected-error{{redundant conformance of 'MFExplicitSub1' to protocol 'P1'}}
// ---------------------------------------------------------------------------
// Suppression of synthesized conformances
// ---------------------------------------------------------------------------
class MFSynthesizedClass1 { }
extension MFSynthesizedClass2 : AnyObject { } // expected-error{{inheritance from non-protocol type 'AnyObject'}}
class MFSynthesizedClass4 { }
extension MFSynthesizedClass4 : AnyObjectRefinement { }
extension MFSynthesizedSubClass2 : AnyObject { } // expected-error{{inheritance from non-protocol type 'AnyObject'}}
extension MFSynthesizedSubClass3 : AnyObjectRefinement { }
class MFSynthesizedSubClass4 : MFSynthesizedClass2 { }
extension MFSynthesizedEnum1 : RawRepresentable { }
enum MFSynthesizedEnum2 : Int { case none = 0 }
// ===========================================================================
// Tests with conformances in imported modules
// ===========================================================================
extension MMExplicit1 : MMP1 { } // expected-warning{{conformance of 'MMExplicit1' to protocol 'MMP1' was already stated in the type's module 'placement_module_A'}}
extension MMExplicit1 : MMP2a { } // expected-warning{{MMExplicit1' to protocol 'MMP2a' was already stated in the type's module 'placement_module_A}}
extension MMExplicit1 : MMP3a { } // expected-warning{{conformance of 'MMExplicit1' to protocol 'MMP3a' was already stated in the type's module 'placement_module_A'}}
extension MMExplicit1 : MMP3b { } // okay
extension MMSuper1 : MMP1 { } // expected-warning{{conformance of 'MMSuper1' to protocol 'MMP1' was already stated in the type's module 'placement_module_A'}}
extension MMSuper1 : MMP2a { } // expected-warning{{conformance of 'MMSuper1' to protocol 'MMP2a' was already stated in the type's module 'placement_module_A'}}
extension MMSuper1 : MMP3b { } // okay
extension MMSub1 : AnyObject { } // expected-error{{inheritance from non-protocol type 'AnyObject'}}
extension MMSub2 : MMP1 { } // expected-warning{{conformance of 'MMSub2' to protocol 'MMP1' was already stated in the type's module 'placement_module_A'}}
extension MMSub2 : MMP2a { } // expected-warning{{conformance of 'MMSub2' to protocol 'MMP2a' was already stated in the type's module 'placement_module_A'}}
extension MMSub2 : MMP3b { } // okay
extension MMSub2 : MMAnyObjectRefinement { } // okay
extension MMSub3 : MMP1 { } // expected-warning{{conformance of 'MMSub3' to protocol 'MMP1' was already stated in the type's module 'placement_module_A'}}
extension MMSub3 : MMP2a { } // expected-warning{{conformance of 'MMSub3' to protocol 'MMP2a' was already stated in the type's module 'placement_module_A'}}
extension MMSub3 : MMP3b { } // okay
extension MMSub3 : AnyObject { } // expected-error{{inheritance from non-protocol type 'AnyObject'}}
extension MMSub4 : MMP1 { } // expected-warning{{conformance of 'MMSub4' to protocol 'MMP1' was already stated in the type's module 'placement_module_B'}}
extension MMSub4 : MMP2a { } // expected-warning{{conformance of 'MMSub4' to protocol 'MMP2a' was already stated in the type's module 'placement_module_B'}}
extension MMSub4 : MMP3b { } // okay
extension MMSub4 : AnyObjectRefinement { } // okay