Skip to content

[SR-8817] Type nested in function unable to conform to protocols with operator requirements #51325

@ffried

Description

@ffried
Previous ID SR-8817
Radar None
Original Reporter @ffried
Type Bug
Status Resolved
Resolution Duplicate

Attachment: Download

Environment
Apple Swift version 4.2 (swiftlang-1000.11.37.1 clang-1000.11.45.1)
Target: x86_64-apple-darwin18.0.0

Also happens with Swift 4.1 in Xcode 9.4.1

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug
Assignee None
Priority Medium

md5: 7df70af54efa8d7dc9ecb55e48ac9d5a

duplicates:

  • SR-8696 Types nested in functions and their operator functions.

Issue Description:

The following code emits an error that SomeComparable does not conform to Comparable:

func someComparableFunc() {
   struct SomeComparable: Comparable {
      static func == (lhs: SomeComparable, rhs: SomeComparable) -> Bool { return false }
      static func < (lhs: SomeComparable, rhs: SomeComparable) -> Bool { return true }
   }
}

The only requirement (<) is implemented, though.

Output:

$ swift s42_nestedStructConformances.swift 
s42_nestedStructConformances.swift:2:11: error: type 'SomeComparable' does not conform to protocol 'Comparable'
   struct SomeComparable: Comparable {
          ^
Swift.<:1:13: note: candidate has non-matching type '((), ()) -> Bool'
public func < (lhs: (), rhs: ()) -> Bool
            ^
Swift.<:1:13: note: candidate has non-matching type '<A, B where A : Comparable, B : Comparable> ((A, B), (A, B)) -> Bool'
public func < <A, B>(lhs: (A, B), rhs: (A, B)) -> Bool where A : Comparable, B : Comparable
            ^
Swift.<:1:13: note: candidate has non-matching type '<A, B, C where A : Comparable, B : Comparable, C : Comparable> ((A, B, C), (A, B, C)) -> Bool'
public func < <A, B, C>(lhs: (A, B, C), rhs: (A, B, C)) -> Bool where A : Comparable, B : Comparable, C : Comparable
            ^
Swift.<:1:13: note: candidate has non-matching type '<A, B, C, D where A : Comparable, B : Comparable, C : Comparable, D : Comparable> ((A, B, C, D), (A, B, C, D)) -> Bool'
public func < <A, B, C, D>(lhs: (A, B, C, D), rhs: (A, B, C, D)) -> Bool where A : Comparable, B : Comparable, C : Comparable, D : Comparable
            ^
Swift.<:1:13: note: candidate has non-matching type '<A, B, C, D, E where A : Comparable, B : Comparable, C : Comparable, D : Comparable, E : Comparable> ((A, B, C, D, E), (A, B, C, D, E)) -> Bool'
public func < <A, B, C, D, E>(lhs: (A, B, C, D, E), rhs: (A, B, C, D, E)) -> Bool where A : Comparable, B : Comparable, C : Comparable, D : Comparable, E : Comparable
            ^
Swift.<:1:13: note: candidate has non-matching type '<A, B, C, D, E, F where A : Comparable, B : Comparable, C : Comparable, D : Comparable, E : Comparable, F : Comparable> ((A, B, C, D, E, F), (A, B, C, D, E, F)) -> Bool'
public func < <A, B, C, D, E, F>(lhs: (A, B, C, D, E, F), rhs: (A, B, C, D, E, F)) -> Bool where A : Comparable, B : Comparable, C : Comparable, D : Comparable, E : Comparable, F : Comparable
            ^
Swift.Character:2:24: note: candidate has non-matching type '(Character, Character) -> Bool'
    public static func < (lhs: Character, rhs: Character) -> Bool
                       ^
Swift.Character.UnicodeScalarView.Index:2:24: note: candidate has non-matching type '(Character.UnicodeScalarView.Index, Character.UnicodeScalarView.Index) -> Bool'
    public static func < (lhs: Character.UnicodeScalarView.Index, rhs: Character.UnicodeScalarView.Index) -> Bool
                       ^
Swift.ClosedRange<Bound>.Index:3:24: note: candidate has non-matching type '<Bound> (ClosedRange<Bound>.Index, ClosedRange<Bound>.Index) -> Bool'
    public static func < (lhs: ClosedRange<Bound>.Index, rhs: ClosedRange<Bound>.Index) -> Bool
                       ^
Swift.Dictionary<Key, Value>.Index:3:24: note: candidate has non-matching type '<Key, Value> (Dictionary<Key, Value>.Index, Dictionary<Key, Value>.Index) -> Bool'
    public static func < (lhs: Dictionary<Key, Value>.Index, rhs: Dictionary<Key, Value>.Index) -> Bool
                       ^
Swift.LazyDropWhileCollection<Base>.Index:3:24: note: candidate has non-matching type '<Base> (LazyDropWhileCollection<Base>.Index, LazyDropWhileCollection<Base>.Index) -> Bool'
    public static func < (lhs: LazyDropWhileCollection<Base>.Index, rhs: LazyDropWhileCollection<Base>.Index) -> Bool
                       ^
Swift.FlattenCollection<Base>.Index:2:24: note: candidate has non-matching type '<Base> (FlattenCollection<Base>.Index, FlattenCollection<Base>.Index) -> Bool'
    public static func < (lhs: FlattenCollection<Base>.Index, rhs: FlattenCollection<Base>.Index) -> Bool
                       ^
Swift.FloatingPoint:3:24: note: candidate has non-matching type '<Self> (Self, Self) -> Bool'
    public static func < (lhs: Self, rhs: Self) -> Bool
                       ^
Swift.BinaryInteger:4:24: note: candidate has non-matching type '<Self, Other> (Self, Other) -> Bool'
    public static func < <Other>(lhs: Self, rhs: Other) -> Bool where Other : BinaryInteger
                       ^
Swift.UInt8:12:24: note: candidate has non-matching type '(UInt8, UInt8) -> Bool'
    public static func < (lhs: UInt8, rhs: UInt8) -> Bool
                       ^
Swift.Int8:12:24: note: candidate has non-matching type '(Int8, Int8) -> Bool'
    public static func < (lhs: Int8, rhs: Int8) -> Bool
                       ^
Swift.UInt16:12:24: note: candidate has non-matching type '(UInt16, UInt16) -> Bool'
    public static func < (lhs: UInt16, rhs: UInt16) -> Bool
                       ^
Swift.Int16:12:24: note: candidate has non-matching type '(Int16, Int16) -> Bool'
    public static func < (lhs: Int16, rhs: Int16) -> Bool
                       ^
Swift.UInt32:12:24: note: candidate has non-matching type '(UInt32, UInt32) -> Bool'
    public static func < (lhs: UInt32, rhs: UInt32) -> Bool
                       ^
Swift.Int32:14:24: note: candidate has non-matching type '(Int32, Int32) -> Bool'
    public static func < (lhs: Int32, rhs: Int32) -> Bool
                       ^
Swift.UInt64:12:24: note: candidate has non-matching type '(UInt64, UInt64) -> Bool'
    public static func < (lhs: UInt64, rhs: UInt64) -> Bool
                       ^
Swift.Int64:14:24: note: candidate has non-matching type '(Int64, Int64) -> Bool'
    public static func < (lhs: Int64, rhs: Int64) -> Bool
                       ^
Swift.UInt:12:24: note: candidate has non-matching type '(UInt, UInt) -> Bool'
    public static func < (lhs: UInt, rhs: UInt) -> Bool
                       ^
Swift.Int:12:24: note: candidate has non-matching type '(Int, Int) -> Bool'
    public static func < (lhs: Int, rhs: Int) -> Bool
                       ^
Swift.Unicode.Scalar:2:24: note: candidate has non-matching type '(Unicode.Scalar, Unicode.Scalar) -> Bool'
    public static func < (lhs: Unicode.Scalar, rhs: Unicode.Scalar) -> Bool
                       ^
Swift.ObjectIdentifier:2:24: note: candidate has non-matching type '(ObjectIdentifier, ObjectIdentifier) -> Bool'
    public static func < (lhs: ObjectIdentifier, rhs: ObjectIdentifier) -> Bool
                       ^
Swift.LazyPrefixWhileCollection<Base>.Index:3:24: note: candidate has non-matching type '<Base> (LazyPrefixWhileCollection<Base>.Index, LazyPrefixWhileCollection<Base>.Index) -> Bool'
    public static func < (lhs: LazyPrefixWhileCollection<Base>.Index, rhs: LazyPrefixWhileCollection<Base>.Index) -> Bool
                       ^
Swift.ReversedCollection<Base>.Index:3:24: note: candidate has non-matching type '<Base> (ReversedCollection<Base>.Index, ReversedCollection<Base>.Index) -> Bool'
    public static func < (lhs: ReversedCollection<Base>.Index, rhs: ReversedCollection<Base>.Index) -> Bool
                       ^
Swift.Set<Element>.Index:3:24: note: candidate has non-matching type '<Element> (Set<Element>.Index, Set<Element>.Index) -> Bool'
    public static func < (lhs: Set<Element>.Index, rhs: Set<Element>.Index) -> Bool
                       ^
Swift.Strideable:2:24: note: candidate has non-matching type '<Self> (Self, Self) -> Bool'
    public static func < (x: Self, y: Self) -> Bool
                       ^
Swift.StringProtocol:4:24: note: candidate has non-matching type '<Self, R> (Self, R) -> Bool'
    public static func < <R>(lhs: Self, rhs: R) -> Bool where R : StringProtocol
                       ^
Swift.String:2:24: note: candidate has non-matching type '(String, String) -> Bool'
    public static func < (lhs: String, rhs: String) -> Bool
                       ^
Swift.String.Index:2:24: note: candidate has non-matching type '(String.Index, String.Index) -> Bool'
    public static func < (lhs: String.Index, rhs: String.Index) -> Bool
                       ^
Swift._UIntBuffer<Storage, Element>:4:28: note: candidate has non-matching type '<Storage, Element> (_UIntBuffer<Storage, Element>.Index, _UIntBuffer<Storage, Element>.Index) -> Bool'
        public static func < (lhs: _UIntBuffer<Storage, Element>.Index, rhs: _UIntBuffer<Storage, Element>.Index) -> Bool
                           ^
Swift.UnsafeMutablePointer<Pointee>:2:24: note: candidate has non-matching type '<Pointee> (UnsafeMutablePointer<Pointee>, UnsafeMutablePointer<Pointee>) -> Bool'
    public static func < (lhs: UnsafeMutablePointer<Pointee>, rhs: UnsafeMutablePointer<Pointee>) -> Bool
                       ^
Swift.UnsafePointer<Pointee>:2:24: note: candidate has non-matching type '<Pointee> (UnsafePointer<Pointee>, UnsafePointer<Pointee>) -> Bool'
    public static func < (lhs: UnsafePointer<Pointee>, rhs: UnsafePointer<Pointee>) -> Bool
                       ^
Swift.UnsafeMutableRawPointer:2:24: note: candidate has non-matching type '(UnsafeMutableRawPointer, UnsafeMutableRawPointer) -> Bool'
    public static func < (lhs: UnsafeMutableRawPointer, rhs: UnsafeMutableRawPointer) -> Bool
                       ^
Swift.UnsafeRawPointer:2:24: note: candidate has non-matching type '(UnsafeRawPointer, UnsafeRawPointer) -> Bool'
    public static func < (lhs: UnsafeRawPointer, rhs: UnsafeRawPointer) -> Bool
                       ^
Swift._ValidUTF8Buffer<Storage>:4:28: note: candidate has non-matching type '<Storage> (_ValidUTF8Buffer<Storage>.Index, _ValidUTF8Buffer<Storage>.Index) -> Bool'
        public static func < (lhs: _ValidUTF8Buffer<Storage>.Index, rhs: _ValidUTF8Buffer<Storage>.Index) -> Bool
                           ^
Swift._SwiftNSOperatingSystemVersion:3:24: note: candidate has non-matching type '(_SwiftNSOperatingSystemVersion, _SwiftNSOperatingSystemVersion) -> Bool'
    public static func < (lhs: _SwiftNSOperatingSystemVersion, rhs: _SwiftNSOperatingSystemVersion) -> Bool
                       ^
Swift.AnyIndex:3:24: note: candidate has non-matching type '(AnyIndex, AnyIndex) -> Bool'
    public static func < (lhs: AnyIndex, rhs: AnyIndex) -> Bool
                       ^
Swift.Comparable:2:24: note: protocol requires function '<' with type '(SomeComparable, SomeComparable) -> Bool'; do you want to add a stub?
    public static func < (lhs: Self, rhs: Self) -> Bool

When trying the same with Equatable, the conformance seems to be accepted, but the implemented == func is not called:

func someEquatableFunc() {
   struct SomeEquatable: Equatable {
      static var didCallEquatable = false
      static func == (lhs: SomeEquatable, rhs: SomeEquatable) -> Bool {
          didCallEquatable = true
          return true
      }
   }
   _ = SomeEquatable() == SomeEquatable()
   print(SomeEquatable.didCallEquatable) // -> false
}
someEquatableFunc()

Metadata

Metadata

Assignees

No one assigned

    Labels

    compilerThe Swift compiler itselfconformancesFeature → protocol: protocol conformancesnested typesFeature: nested typesswift 4.2type checkerArea → compiler: Semantic analysistypesFeature: typesunexpected errorBug: Unexpected error

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions