Files
swift-mirror/test/decl/protocol/conforms/placement.swift
Doug Gregor 9271a24a92 Introduce a protocol conformance registry for nominal types.
(Note that this registry isn't fully enabled yet; it's built so that
we can test it, but has not yet taken over the primary task of
managing conformances from the existing system).

The conformance registry tracks all of the protocols to which a
particular nominal type conforms, including those for which
conformance was explicitly specified, implied by other explicit
conformances, inherited from a superclass, or synthesized by the
implementation.

The conformance registry is a lazily-built data structure designed for
multi-file support (which has been a problematic area for protocol
conformances). It allows one to query for the conformances of a type
to a particular protocol, enumerate all protocols to which a type
conforms, and enumerate all of the conformances that are associated
with a particular declaration context (important to eliminate
duplicated witness tables).

The conformance registry diagnoses conflicts and ambiguities among
different conformances of the same type to the same protocol. There
are three common cases where we'll see a diagnostic:

1) Redundant explicit conformance of a type to a protocol:

    protocol P { }
    struct X : P {  }
    extension X : P { } // error: redundant explicit conformance

2) Explicit conformance to a protocol that collides with an inherited
  conformance:

    protocol P { }
    class Super : P { }
    class Sub : Super, P { } // error: redundant explicit conformance

3) Ambiguous placement of an implied conformance:

    protocol P1 { }
    protocol P2 : P1 { }
    protocol P3 : P1 { }

    struct Y { }
    extension Y : P2 { }
    extension Y : P3 { } // error: ambiguous implied conformance to 'P1'

  This happens when two different explicit conformances (here, P2 and
  P3) placed on different declarations (e.g., two extensions, or the
  original definition and other extension) both imply the same
  conformance (P1), and neither of the explicit conformances imply
  each other. We require the user to explicitly specify the ambiguous
  conformance to break the ambiguity and associate the witness table
  with a specific context.

Swift SVN r26067
2015-03-12 21:11:23 +00:00

210 lines
10 KiB
Swift

// RUN: rm -rf %t
// RUN: mkdir %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 -parse -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 { }
// ---------------------------------------------------------------------------
// Multiple implicit conformances, with ambiguities
// ---------------------------------------------------------------------------
struct BadMultipleImplicit1 : P2a { } // expected-note{{'BadMultipleImplicit1' implicitly conforms to protocol 'P1' (via conformance to 'P2a') here}}
extension BadMultipleImplicit1 : P2b { } // expected-error{{ambiguous implied conformance of 'BadMultipleImplicit1' to protocol 'P1' (via 'P2b') requires explicit conformance}}
// expected-note@-1{{implied protocol conformance 'P1' here can be made explicit}}{{34-34=P1, }}
// ---------------------------------------------------------------------------
// 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
// ---------------------------------------------------------------------------
// 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 { }
class SynthesizedClass2 { }
extension SynthesizedClass2 : AnyObject { }
class SynthesizedClass3 : AnyObjectRefinement { }
class SynthesizedClass4 { }
extension SynthesizedClass4 : AnyObjectRefinement { }
class SynthesizedSubClass1 : SynthesizedClass1, AnyObject { } // expected-error{{redundant conformance of 'SynthesizedSubClass1' to protocol 'AnyObject'}}
// expected-note@-1{{'SynthesizedSubClass1' inherits conformance to protocol 'AnyObject' from superclass here}}
class SynthesizedSubClass2 : SynthesizedClass2 { } // expected-note{{'SynthesizedSubClass2' inherits conformance to protocol 'AnyObject' from superclass here}}
extension SynthesizedSubClass2 : AnyObject { } // expected-error{{redundant conformance of 'SynthesizedSubClass2' to protocol '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 { }
// ---------------------------------------------------------------------------
// Multiple implicit conformances, with ambiguities
// ---------------------------------------------------------------------------
extension MFBadMultipleImplicit1 : P2b { } // expected-error{{ambiguous implied conformance of 'MFBadMultipleImplicit1' to protocol 'P1' (via 'P2b') requires explicit conformance}}
// expected-note@-1{{implied protocol conformance 'P1' here can be made explicit}}{{36-36=P1, }}
// ---------------------------------------------------------------------------
// 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 { }
class MFSynthesizedClass4 { }
extension MFSynthesizedClass4 : AnyObjectRefinement { }
extension MFSynthesizedSubClass2 : AnyObject { } // expected-error{{redundant conformance of 'MFSynthesizedSubClass2' to protocol '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-error{{redundant conformance of 'MMExplicit1' to protocol 'MMP1'}}
extension MMExplicit1 : MMP2a { } // expected-error{{redundant conformance of 'MMExplicit1' to protocol 'MMP2a'}}
extension MMExplicit1 : MMP3a { } // expected-error{{redundant conformance of 'MMExplicit1' to protocol 'MMP3a'}}
extension MMExplicit1 : MMP3b { } // okay
extension MMSuper1 : MMP1 { } // expected-error{{redundant conformance of 'MMSuper1' to protocol 'MMP1'}}
extension MMSuper1 : MMP2a { } // expected-error{{redundant conformance of 'MMSuper1' to protocol 'MMP2a'}}
extension MMSuper1 : MMP3b { } // okay
extension MMSub1 : AnyObject { } // expected-error{{redundant conformance of 'MMSub1' to protocol 'AnyObject'}}
extension MMSub2 : MMP1 { } // expected-error{{redundant conformance of 'MMSub2' to protocol 'MMP1'}}
extension MMSub2 : MMP2a { } // expected-error{{redundant conformance of 'MMSub2' to protocol 'MMP2a'}}
extension MMSub2 : MMP3b { } // okay
extension MMSub2 : MMAnyObjectRefinement { } // okay
extension MMSub3 : MMP1 { } // expected-error{{redundant conformance of 'MMSub3' to protocol 'MMP1'}}
extension MMSub3 : MMP2a { } // expected-error{{redundant conformance of 'MMSub3' to protocol 'MMP2a'}}
extension MMSub3 : MMP3b { } // okay
extension MMSub3 : AnyObject { } // expected-error{{redundant conformance of 'MMSub3' to protocol 'AnyObject'}}
extension MMSub4 : MMP1 { } // expected-error{{redundant conformance of 'MMSub4' to protocol 'MMP1'}}
extension MMSub4 : MMP2a { } // expected-error{{redundant conformance of 'MMSub4' to protocol 'MMP2a'}}
extension MMSub4 : MMP3b { } // okay
extension MMSub4 : AnyObjectRefinement { } // okay